mirror of
https://github.com/open-sdr/openwifi.git
synced 2024-12-23 15:32:41 +00:00
udpate ad9361 driver related stuffs:
we do not maintain our own (modified) ad9361 driver anymore! The original ad9361 driver in the Linux kernel tree can be used with some extra EXPORT_SYMBOL.
This commit is contained in:
parent
23ba65e4fa
commit
56fcab2044
@ -1,11 +0,0 @@
|
||||
# by Xianjun jiao. putaoshu@msn.com; xianjun.jiao@imec.be
|
||||
|
||||
ad9361_drv-y := ad9361.o ad9361_conv.o
|
||||
obj-m += ad9361_drv.o
|
||||
|
||||
all:
|
||||
make -C $(KDIR) M=$(PWD) modules
|
||||
# ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
|
||||
|
||||
clean:
|
||||
rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order
|
6
driver/ad9361/README.md
Normal file
6
driver/ad9361/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
<!--
|
||||
Author: Xianjun Jiao
|
||||
SPDX-FileCopyrightText: 2021 UGent
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
We don't maintain our own (modified) ad9361 driver anymore! The original ad9361 driver in the Linux kernel tree can be used with some extra EXPORT_SYMBOL.
|
@ -1,9 +1,10 @@
|
||||
/*
|
||||
* AD9361 Agile RF Transceiver
|
||||
* SPDX-FileCopyrightText: Copyright 2013-2015 Analog Devices Inc.
|
||||
* Modified by Xianjun jiao
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
*
|
||||
* Copyright 2013-2015 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
//#define DEBUG
|
||||
//#define _DEBUG
|
||||
#include <linux/module.h>
|
||||
@ -1628,7 +1629,6 @@ static int ad9361_get_rx_gain(struct ad9361_rf_phy *phy,
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_get_rx_gain);
|
||||
|
||||
static u8 ad9361_ensm_get_state(struct ad9361_rf_phy *phy)
|
||||
{
|
||||
@ -2006,7 +2006,6 @@ out:
|
||||
return rc;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_set_rx_gain);
|
||||
|
||||
static int ad9361_gc_update(struct ad9361_rf_phy *phy)
|
||||
{
|
||||
@ -2174,9 +2173,8 @@ static int ad9361_set_gain_ctrl_mode(struct ad9361_rf_phy *phy,
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_set_gain_ctrl_mode);
|
||||
|
||||
int ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi)
|
||||
static int ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi)
|
||||
{
|
||||
struct spi_device *spi = phy->spi;
|
||||
u8 reg_val_buf[6];
|
||||
@ -2205,7 +2203,6 @@ int ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi)
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_read_rssi);
|
||||
|
||||
static int ad9361_rx_adc_setup(struct ad9361_rf_phy *phy, unsigned long bbpll_freq,
|
||||
unsigned long adc_sampl_freq_Hz)
|
||||
@ -3734,7 +3731,6 @@ int ad9361_ctrl_outs_setup(struct ad9361_rf_phy *phy,
|
||||
return ad9361_spi_write(spi, REG_CTRL_OUTPUT_ENABLE, ctrl->en_mask); // Ctrl Out [7:0] output enable
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_ctrl_outs_setup);
|
||||
|
||||
//************************************************************
|
||||
// Setup GPO
|
||||
//************************************************************
|
||||
@ -3780,7 +3776,7 @@ static int ad9361_gpo_setup(struct ad9361_rf_phy *phy, struct gpo_control *ctrl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ad9361_rssi_setup(struct ad9361_rf_phy *phy,
|
||||
static int ad9361_rssi_setup(struct ad9361_rf_phy *phy,
|
||||
struct rssi_control *ctrl,
|
||||
bool is_update)
|
||||
{
|
||||
@ -3871,7 +3867,6 @@ int ad9361_rssi_setup(struct ad9361_rf_phy *phy,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_rssi_setup);
|
||||
|
||||
static int ad9361_bb_clk_change_handler(struct ad9361_rf_phy *phy)
|
||||
{
|
||||
@ -4075,12 +4070,6 @@ static int ad9361_validate_trx_clock_chain(struct ad9361_rf_phy *phy,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int ad9361_clk_set_rate(struct clk *clk, unsigned long rate) {
|
||||
clk_set_rate(clk, rate);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_clk_set_rate);
|
||||
|
||||
static int ad9361_set_trx_clock_chain(struct ad9361_rf_phy *phy,
|
||||
unsigned long *rx_path_clks,
|
||||
unsigned long *tx_path_clks)
|
||||
@ -5223,7 +5212,7 @@ static int ad9361_do_calib_run(struct ad9361_rf_phy *phy, u32 cal, int arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy,
|
||||
static int ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy,
|
||||
u32 rf_rx_bw, u32 rf_tx_bw)
|
||||
{
|
||||
struct ad9361_rf_phy_state *st = phy->state;
|
||||
@ -5257,7 +5246,6 @@ int ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_update_rf_bandwidth);
|
||||
|
||||
static int ad9361_verify_fir_filter_coef(struct ad9361_rf_phy *phy,
|
||||
enum fir_dest dest,
|
||||
|
@ -1,252 +0,0 @@
|
||||
/*
|
||||
* AD9361
|
||||
* SPDX-FileCopyrightText: Copyright 2013-2018 Analog Devices Inc
|
||||
* Modified by Xianjun jiao
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef IIO_FREQUENCY_AD9361_H_
|
||||
#define IIO_FREQUENCY_AD9361_H_
|
||||
|
||||
#include "ad9361_regs.h"
|
||||
|
||||
enum ad9361_clocks {
|
||||
BB_REFCLK,
|
||||
RX_REFCLK,
|
||||
TX_REFCLK,
|
||||
BBPLL_CLK,
|
||||
ADC_CLK,
|
||||
R2_CLK,
|
||||
R1_CLK,
|
||||
CLKRF_CLK,
|
||||
RX_SAMPL_CLK,
|
||||
DAC_CLK,
|
||||
T2_CLK,
|
||||
T1_CLK,
|
||||
CLKTF_CLK,
|
||||
TX_SAMPL_CLK,
|
||||
RX_RFPLL_INT,
|
||||
TX_RFPLL_INT,
|
||||
RX_RFPLL_DUMMY,
|
||||
TX_RFPLL_DUMMY,
|
||||
RX_RFPLL,
|
||||
TX_RFPLL,
|
||||
NUM_AD9361_CLKS,
|
||||
};
|
||||
|
||||
enum debugfs_cmd {
|
||||
DBGFS_NONE,
|
||||
DBGFS_INIT,
|
||||
DBGFS_LOOPBACK,
|
||||
DBGFS_BIST_PRBS,
|
||||
DBGFS_BIST_TONE,
|
||||
DBGFS_BIST_DT_ANALYSIS,
|
||||
DBGFS_RXGAIN_1,
|
||||
DBGFS_RXGAIN_2,
|
||||
DBGFS_MCS,
|
||||
DBGFS_CAL_SW_CTRL,
|
||||
DBGFS_DIGITAL_TUNE,
|
||||
DBGFS_GPO_SET,
|
||||
};
|
||||
|
||||
enum dig_tune_flags {
|
||||
BE_VERBOSE = 1,
|
||||
BE_MOREVERBOSE = 2,
|
||||
DO_IDELAY = 4,
|
||||
DO_ODELAY = 8,
|
||||
SKIP_STORE_RESULT = 16,
|
||||
RESTORE_DEFAULT = 32,
|
||||
};
|
||||
|
||||
enum ad9361_bist_mode {
|
||||
BIST_DISABLE,
|
||||
BIST_INJ_TX,
|
||||
BIST_INJ_RX,
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_AD9361,
|
||||
ID_AD9364,
|
||||
ID_AD9361_2,
|
||||
ID_AD9363A,
|
||||
};
|
||||
|
||||
enum rx_port_sel {
|
||||
RX_A_BALANCED, /* 0 = (RX1A_N & RX1A_P) and (RX2A_N & RX2A_P) enabled; balanced */
|
||||
RX_B_BALANCED, /* 1 = (RX1B_N & RX1B_P) and (RX2B_N & RX2B_P) enabled; balanced */
|
||||
RX_C_BALANCED, /* 2 = (RX1C_N & RX1C_P) and (RX2C_N & RX2C_P) enabled; balanced */
|
||||
RX_A_N, /* 3 = RX1A_N and RX2A_N enabled; unbalanced */
|
||||
RX_A_P, /* 4 = RX1A_P and RX2A_P enabled; unbalanced */
|
||||
RX_B_N, /* 5 = RX1B_N and RX2B_N enabled; unbalanced */
|
||||
RX_B_P, /* 6 = RX1B_P and RX2B_P enabled; unbalanced */
|
||||
RX_C_N, /* 7 = RX1C_N and RX2C_N enabled; unbalanced */
|
||||
RX_C_P, /* 8 = RX1C_P and RX2C_P enabled; unbalanced */
|
||||
TX_MON1, /* 9 = TX_MON1 enabled */
|
||||
TX_MON2, /* 10 = TX_MON2 enabled */
|
||||
TX_MON1_2, /* 11 = TX_MON1 & TX_MON2 enabled */
|
||||
};
|
||||
|
||||
enum tx_port_sel {
|
||||
TX_A,
|
||||
TX_B,
|
||||
};
|
||||
|
||||
enum digital_tune_skip_mode {
|
||||
TUNE_RX_TX,
|
||||
SKIP_TX,
|
||||
SKIP_ALL,
|
||||
};
|
||||
|
||||
enum rssi_restart_mode {
|
||||
AGC_IN_FAST_ATTACK_MODE_LOCKS_THE_GAIN,
|
||||
EN_AGC_PIN_IS_PULLED_HIGH,
|
||||
ENTERS_RX_MODE,
|
||||
GAIN_CHANGE_OCCURS,
|
||||
SPI_WRITE_TO_REGISTER,
|
||||
GAIN_CHANGE_OCCURS_OR_EN_AGC_PIN_PULLED_HIGH,
|
||||
};
|
||||
|
||||
struct ctrl_outs_control {
|
||||
u8 index;
|
||||
u8 en_mask;
|
||||
};
|
||||
|
||||
struct rssi_control {
|
||||
enum rssi_restart_mode restart_mode;
|
||||
bool rssi_unit_is_rx_samples; /* default unit is time */
|
||||
u32 rssi_delay;
|
||||
u32 rssi_wait;
|
||||
u32 rssi_duration;
|
||||
};
|
||||
|
||||
struct rf_rssi {
|
||||
u32 ant; /* Antenna number for which RSSI is reported */
|
||||
u32 symbol; /* Runtime RSSI */
|
||||
u32 preamble; /* Initial RSSI */
|
||||
s32 multiplier; /* Multiplier to convert reported RSSI */
|
||||
u8 duration; /* Duration to be considered for measuring */
|
||||
};
|
||||
|
||||
struct ad9361_rf_phy;
|
||||
struct ad9361_debugfs_entry {
|
||||
struct ad9361_rf_phy *phy;
|
||||
const char *propname;
|
||||
void *out_value;
|
||||
u32 val;
|
||||
u8 size;
|
||||
u8 cmd;
|
||||
};
|
||||
|
||||
struct ad9361_dig_tune_data {
|
||||
u32 bist_loopback_mode;
|
||||
u32 bist_config;
|
||||
u32 ensm_state;
|
||||
u8 skip_mode;
|
||||
};
|
||||
|
||||
struct refclk_scale {
|
||||
struct clk_hw hw;
|
||||
struct spi_device *spi;
|
||||
struct ad9361_rf_phy *phy;
|
||||
unsigned long rate;
|
||||
u32 mult;
|
||||
u32 div;
|
||||
enum ad9361_clocks source;
|
||||
};
|
||||
|
||||
struct ad9361_rf_phy_state;
|
||||
struct ad9361_ext_band_ctl;
|
||||
|
||||
struct ad9361_rf_phy {
|
||||
struct spi_device *spi;
|
||||
struct clk *clk_refin;
|
||||
struct clk *clk_ext_lo_rx;
|
||||
struct clk *clk_ext_lo_tx;
|
||||
struct clk *clks[NUM_AD9361_CLKS];
|
||||
struct notifier_block clk_nb_tx;
|
||||
struct notifier_block clk_nb_rx;
|
||||
struct refclk_scale clk_priv[NUM_AD9361_CLKS];
|
||||
struct clk_onecell_data clk_data;
|
||||
struct ad9361_phy_platform_data *pdata;
|
||||
struct ad9361_debugfs_entry debugfs_entry[182];
|
||||
struct bin_attribute bin;
|
||||
struct bin_attribute bin_gt;
|
||||
struct iio_dev *indio_dev;
|
||||
struct work_struct work;
|
||||
struct completion complete;
|
||||
struct gain_table_info *gt_info;
|
||||
char *bin_attr_buf;
|
||||
u32 ad9361_debugfs_entry_index;
|
||||
|
||||
struct ad9361_ext_band_ctl *ext_band_ctl;
|
||||
struct ad9361_rf_phy_state *state;
|
||||
};
|
||||
|
||||
int ad9361_ctrl_outs_setup(struct ad9361_rf_phy *phy, struct ctrl_outs_control *ctrl);
|
||||
int ad9361_clk_set_rate(struct clk *clk, unsigned long rate);
|
||||
int ad9361_rssi_setup(struct ad9361_rf_phy *phy,
|
||||
struct rssi_control *ctrl,
|
||||
bool is_update);
|
||||
int ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi);
|
||||
int ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy,u32 rf_rx_bw, u32 rf_tx_bw);
|
||||
|
||||
ssize_t ad9361_dig_interface_timing_analysis(struct ad9361_rf_phy *phy,
|
||||
char *buf, unsigned buflen);
|
||||
int ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable);
|
||||
int ad9361_register_axi_converter(struct ad9361_rf_phy *phy);
|
||||
struct ad9361_rf_phy* ad9361_spi_to_phy(struct spi_device *spi);
|
||||
int ad9361_spi_read(struct spi_device *spi, u32 reg);
|
||||
int ad9361_spi_write(struct spi_device *spi, u32 reg, u32 val);
|
||||
int ad9361_bist_loopback(struct ad9361_rf_phy *phy, unsigned mode);
|
||||
int ad9361_bist_prbs(struct ad9361_rf_phy *phy, enum ad9361_bist_mode mode);
|
||||
int ad9361_find_opt(u8 *field, u32 size, u32 *ret_start);
|
||||
int ad9361_ensm_mode_disable_pinctrl(struct ad9361_rf_phy *phy);
|
||||
int ad9361_ensm_mode_restore_pinctrl(struct ad9361_rf_phy *phy);
|
||||
void ad9361_ensm_force_state(struct ad9361_rf_phy *phy, u8 ensm_state);
|
||||
void ad9361_ensm_restore_state(struct ad9361_rf_phy *phy, u8 ensm_state);
|
||||
void ad9361_ensm_restore_prev_state(struct ad9361_rf_phy *phy);
|
||||
int ad9361_set_trx_clock_chain_freq(struct ad9361_rf_phy *phy,
|
||||
unsigned long freq);
|
||||
int ad9361_set_trx_clock_chain_default(struct ad9361_rf_phy *phy);
|
||||
int ad9361_dig_tune(struct ad9361_rf_phy *phy, unsigned long max_freq,
|
||||
enum dig_tune_flags flags);
|
||||
int ad9361_tx_mute(struct ad9361_rf_phy *phy, u32 state);
|
||||
int ad9361_get_tx_atten(struct ad9361_rf_phy *phy, u32 tx_num);
|
||||
int ad9361_set_tx_atten(struct ad9361_rf_phy *phy, u32 atten_mdb, bool tx1, bool tx2, bool immed);
|
||||
int ad9361_write_bist_reg(struct ad9361_rf_phy *phy, u32 val);
|
||||
bool ad9361_uses_rx2tx2(struct ad9361_rf_phy *phy);
|
||||
int ad9361_get_dig_tune_data(struct ad9361_rf_phy *phy,
|
||||
struct ad9361_dig_tune_data *data);
|
||||
int ad9361_read_clock_data_delays(struct ad9361_rf_phy *phy);
|
||||
int ad9361_write_clock_data_delays(struct ad9361_rf_phy *phy);
|
||||
bool ad9361_uses_lvds_mode(struct ad9361_rf_phy *phy);
|
||||
int ad9361_set_rx_port(struct ad9361_rf_phy *phy, enum rx_port_sel sel);
|
||||
int ad9361_set_tx_port(struct ad9361_rf_phy *phy, enum tx_port_sel sel);
|
||||
|
||||
#ifdef CONFIG_AD9361_EXT_BAND_CONTROL
|
||||
int ad9361_register_ext_band_control(struct ad9361_rf_phy *phy);
|
||||
int ad9361_adjust_rx_ext_band_settings(struct ad9361_rf_phy *phy, u64 freq);
|
||||
int ad9361_adjust_tx_ext_band_settings(struct ad9361_rf_phy *phy, u64 freq);
|
||||
void ad9361_unregister_ext_band_control(struct ad9361_rf_phy *phy);
|
||||
#else
|
||||
static inline int ad9361_register_ext_band_control(struct ad9361_rf_phy *phy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int ad9361_adjust_rx_ext_band_settings(
|
||||
struct ad9361_rf_phy *phy, u64 freq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int ad9361_adjust_tx_ext_band_settings(
|
||||
struct ad9361_rf_phy *phy, u64 freq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void ad9361_unregister_ext_band_control(
|
||||
struct ad9361_rf_phy *phy)
|
||||
{}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,819 +0,0 @@
|
||||
/*
|
||||
* AD9361 Agile RF Transceiver
|
||||
* SPDX-FileCopyrightText: Copyright 2013-2017 Analog Devices Inc
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include "ad9361.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_CF_AXI_ADC)
|
||||
#include "cf_axi_adc.h"
|
||||
|
||||
static void ad9361_set_intf_delay(struct ad9361_rf_phy *phy, bool tx,
|
||||
unsigned int clock_delay,
|
||||
unsigned int data_delay, bool clock_changed)
|
||||
{
|
||||
if (clock_changed)
|
||||
ad9361_ensm_force_state(phy, ENSM_STATE_ALERT);
|
||||
ad9361_spi_write(phy->spi,
|
||||
REG_RX_CLOCK_DATA_DELAY + (tx ? 1 : 0),
|
||||
RX_DATA_DELAY(data_delay) |
|
||||
DATA_CLK_DELAY(clock_delay));
|
||||
if (clock_changed)
|
||||
ad9361_ensm_force_state(phy, ENSM_STATE_FDD);
|
||||
}
|
||||
|
||||
static unsigned int ad9361_num_phy_chan(struct axiadc_converter *conv)
|
||||
{
|
||||
if (conv->chip_info->num_channels > 4)
|
||||
return 4;
|
||||
return conv->chip_info->num_channels;
|
||||
}
|
||||
|
||||
static int ad9361_check_pn(struct axiadc_converter *conv, bool tx,
|
||||
unsigned int delay)
|
||||
{
|
||||
struct axiadc_state *st = iio_priv(conv->indio_dev);
|
||||
unsigned int num_chan = ad9361_num_phy_chan(conv);
|
||||
unsigned int chan;
|
||||
|
||||
for (chan = 0; chan < num_chan; chan++)
|
||||
axiadc_write(st, ADI_REG_CHAN_STATUS(chan),
|
||||
ADI_PN_ERR | ADI_PN_OOS);
|
||||
mdelay(delay);
|
||||
|
||||
if (!tx && !(axiadc_read(st, ADI_REG_STATUS) & ADI_STATUS))
|
||||
return 1;
|
||||
|
||||
for (chan = 0; chan < num_chan; chan++) {
|
||||
if (axiadc_read(st, ADI_REG_CHAN_STATUS(chan)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t ad9361_dig_interface_timing_analysis(struct ad9361_rf_phy *phy,
|
||||
char *buf, unsigned buflen)
|
||||
{
|
||||
struct axiadc_converter *conv = spi_get_drvdata(phy->spi);
|
||||
struct ad9361_dig_tune_data data;
|
||||
int i, j, len = 0;
|
||||
int ret;
|
||||
u8 field[16][16];
|
||||
u8 rx;
|
||||
|
||||
if (!conv)
|
||||
return -ENODEV;
|
||||
|
||||
ret = ad9361_get_dig_tune_data(phy, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_dbg(&phy->spi->dev, "%s:\n", __func__);
|
||||
|
||||
rx = ad9361_spi_read(phy->spi, REG_RX_CLOCK_DATA_DELAY);
|
||||
|
||||
/* Mute TX, we don't want to transmit the PRBS */
|
||||
ad9361_tx_mute(phy, 1);
|
||||
|
||||
ad9361_ensm_mode_disable_pinctrl(phy);
|
||||
|
||||
ad9361_bist_loopback(phy, 0);
|
||||
ad9361_bist_prbs(phy, BIST_INJ_RX);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
ad9361_set_intf_delay(phy, false, i, j, j == 0);
|
||||
field[j][i] = ad9361_check_pn(conv, false, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ad9361_ensm_force_state(phy, ENSM_STATE_ALERT);
|
||||
ad9361_spi_write(phy->spi, REG_RX_CLOCK_DATA_DELAY, rx);
|
||||
ad9361_bist_loopback(phy, data.bist_loopback_mode);
|
||||
ad9361_write_bist_reg(phy, data.bist_config);
|
||||
|
||||
ad9361_ensm_mode_restore_pinctrl(phy);
|
||||
ad9361_ensm_restore_state(phy, data.ensm_state);
|
||||
|
||||
ad9361_tx_mute(phy, 0);
|
||||
|
||||
len += snprintf(buf + len, buflen, "CLK: %lu Hz 'o' = PASS\n",
|
||||
clk_get_rate(phy->clks[RX_SAMPL_CLK]));
|
||||
len += snprintf(buf + len, buflen, "DC");
|
||||
for (i = 0; i < 16; i++)
|
||||
len += snprintf(buf + len, buflen, "%x:", i);
|
||||
len += snprintf(buf + len, buflen, "\n");
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
len += snprintf(buf + len, buflen, "%x:", i);
|
||||
for (j = 0; j < 16; j++) {
|
||||
len += snprintf(buf + len, buflen, "%c ",
|
||||
(field[i][j] ? '.' : 'o'));
|
||||
}
|
||||
len += snprintf(buf + len, buflen, "\n");
|
||||
}
|
||||
len += snprintf(buf + len, buflen, "\n");
|
||||
|
||||
return len;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_dig_interface_timing_analysis);
|
||||
|
||||
static ssize_t samples_pps_read(struct iio_dev *indio_dev,
|
||||
uintptr_t private,
|
||||
const struct iio_chan_spec *chan, char *buf)
|
||||
{
|
||||
struct axiadc_converter *conv = iio_device_get_drvdata(indio_dev);
|
||||
struct axiadc_state *st = iio_priv(conv->indio_dev);
|
||||
u32 config, val, mode;
|
||||
|
||||
config = axiadc_read(st, ADI_REG_CONFIG);
|
||||
|
||||
if (!(config & ADI_PPS_RECEIVER_ENABLE))
|
||||
return -ENODEV;
|
||||
|
||||
val = axiadc_read(st, ADI_REG_CLOCKS_PER_PPS_STATUS);
|
||||
if (val & ADI_CLOCKS_PER_PPS_STAT_INVAL)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
mode = axiadc_read(st, ADI_REG_CNTRL);
|
||||
|
||||
/*
|
||||
* Counts DATA_CLK cycles therefore needs to be corrected
|
||||
* for 2rx2tx mode or for LVDS vs. CMOS mode.
|
||||
*/
|
||||
|
||||
val = axiadc_read(st, ADI_REG_CLOCKS_PER_PPS);
|
||||
|
||||
if (!(mode & ADI_R1_MODE))
|
||||
val /= 2;
|
||||
|
||||
if (!(config & ADI_CMOS_OR_LVDS_N))
|
||||
val /= 2;
|
||||
|
||||
return sprintf(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of samples during a 1PPS (Pulse Per Second) interval.
|
||||
*/
|
||||
|
||||
static struct iio_chan_spec_ext_info axiadc_ext_info[] = {
|
||||
{
|
||||
.name = "samples_pps",
|
||||
.read = samples_pps_read,
|
||||
.shared = IIO_SHARED_BY_TYPE,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
#define AIM_CHAN(_chan, _si, _bits, _sign) \
|
||||
{ .type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = _chan, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
|
||||
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
|
||||
BIT(IIO_CHAN_INFO_CALIBPHASE), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||
.ext_info = axiadc_ext_info, \
|
||||
.scan_index = _si, \
|
||||
.scan_type = { \
|
||||
.sign = _sign, \
|
||||
.realbits = _bits, \
|
||||
.storagebits = 16, \
|
||||
.shift = 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define AIM_MC_CHAN(_chan, _si, _bits, _sign) \
|
||||
{ .type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = _chan, \
|
||||
.scan_index = _si, \
|
||||
.scan_type = { \
|
||||
.sign = _sign, \
|
||||
.realbits = _bits, \
|
||||
.storagebits = 16, \
|
||||
.shift = 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
|
||||
static const unsigned long ad9361_2x2_available_scan_masks[] = {
|
||||
0x01, 0x02, 0x04, 0x08, 0x03, 0x0C, /* 1 & 2 chan */
|
||||
0x10, 0x20, 0x40, 0x80, 0x30, 0xC0, /* 1 & 2 chan */
|
||||
0x33, 0xCC, 0xC3, 0x3C, 0x0F, 0xF0, /* 4 chan */
|
||||
0xFF, /* 8 chan */
|
||||
0x00,
|
||||
};
|
||||
|
||||
static const unsigned long ad9361_available_scan_masks[] = {
|
||||
0x01, 0x02, 0x04, 0x08, 0x03, 0x0C, 0x0F,
|
||||
0x00,
|
||||
};
|
||||
|
||||
static const struct axiadc_chip_info axiadc_chip_info_tbl[] = {
|
||||
[ID_AD9361] = {
|
||||
.name = "AD9361",
|
||||
.max_rate = 61440000UL,
|
||||
.max_testmode = 0,
|
||||
.num_channels = 4,
|
||||
.scan_masks = ad9361_available_scan_masks,
|
||||
.channel[0] = AIM_CHAN(0, 0, 12, 'S'),
|
||||
.channel[1] = AIM_CHAN(1, 1, 12, 'S'),
|
||||
.channel[2] = AIM_CHAN(2, 2, 12, 'S'),
|
||||
.channel[3] = AIM_CHAN(3, 3, 12, 'S'),
|
||||
},
|
||||
[ID_AD9361_2] = { /* MCS/MIMO 2x AD9361 */
|
||||
.name = "AD9361-2",
|
||||
.max_rate = 61440000UL,
|
||||
.max_testmode = 0,
|
||||
.num_channels = 8,
|
||||
.num_shadow_slave_channels = 4,
|
||||
.scan_masks = ad9361_2x2_available_scan_masks,
|
||||
.channel[0] = AIM_CHAN(0, 0, 12, 'S'),
|
||||
.channel[1] = AIM_CHAN(1, 1, 12, 'S'),
|
||||
.channel[2] = AIM_CHAN(2, 2, 12, 'S'),
|
||||
.channel[3] = AIM_CHAN(3, 3, 12, 'S'),
|
||||
.channel[4] = AIM_MC_CHAN(4, 4, 12, 'S'),
|
||||
.channel[5] = AIM_MC_CHAN(5, 5, 12, 'S'),
|
||||
.channel[6] = AIM_MC_CHAN(6, 6, 12, 'S'),
|
||||
.channel[7] = AIM_MC_CHAN(7, 7, 12, 'S'),
|
||||
},
|
||||
[ID_AD9364] = {
|
||||
.name = "AD9364",
|
||||
.max_rate = 61440000UL,
|
||||
.max_testmode = 0,
|
||||
.num_channels = 2,
|
||||
.channel[0] = AIM_CHAN(0, 0, 12, 'S'),
|
||||
.channel[1] = AIM_CHAN(1, 1, 12, 'S'),
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static int ad9361_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val,
|
||||
int *val2,
|
||||
long m)
|
||||
{
|
||||
struct axiadc_converter *conv = iio_device_get_drvdata(indio_dev);
|
||||
|
||||
switch (m) {
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
if (!conv->clk)
|
||||
return -ENODEV;
|
||||
|
||||
*val = conv->adc_clk = clk_get_rate(conv->clk);
|
||||
|
||||
return IIO_VAL_INT;
|
||||
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ad9361_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val,
|
||||
int val2,
|
||||
long mask)
|
||||
{
|
||||
struct axiadc_converter *conv = iio_device_get_drvdata(indio_dev);
|
||||
unsigned long r_clk;
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
if (!conv->clk)
|
||||
return -ENODEV;
|
||||
|
||||
if (chan->extend_name)
|
||||
return -ENODEV;
|
||||
|
||||
r_clk = clk_round_rate(conv->clk, val);
|
||||
if (r_clk < 0 || r_clk > conv->chip_info->max_rate) {
|
||||
dev_warn(&conv->spi->dev,
|
||||
"Error setting ADC sample rate %ld", r_clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(conv->clk, r_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable)
|
||||
{
|
||||
struct axiadc_converter *conv = spi_get_drvdata(phy->spi);
|
||||
struct axiadc_state *st;
|
||||
unsigned reg, addr, chan, version;
|
||||
|
||||
if (!conv)
|
||||
return -ENODEV;
|
||||
|
||||
st = iio_priv(conv->indio_dev);
|
||||
version = axiadc_read(st, 0x4000);
|
||||
|
||||
/* Still there but implemented a bit different */
|
||||
if (ADI_AXI_PCORE_VER_MAJOR(version) > 7)
|
||||
addr = 0x4418;
|
||||
else
|
||||
addr = 0x4414;
|
||||
|
||||
for (chan = 0; chan < conv->chip_info->num_channels; chan++) {
|
||||
reg = axiadc_read(st, addr + (chan) * 0x40);
|
||||
|
||||
if (ADI_AXI_PCORE_VER_MAJOR(version) > 7) {
|
||||
if (enable) {
|
||||
if (reg != 0x8) {
|
||||
conv->scratch_reg[chan] = reg;
|
||||
reg = 0x8;
|
||||
}
|
||||
} else if (reg == 0x8) {
|
||||
reg = conv->scratch_reg[chan];
|
||||
}
|
||||
} else {
|
||||
/* DAC_LB_ENB If set enables loopback of receive data */
|
||||
if (enable)
|
||||
reg |= BIT(1);
|
||||
else
|
||||
reg &= ~BIT(1);
|
||||
}
|
||||
axiadc_write(st, addr + (chan) * 0x40, reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_hdl_loopback);
|
||||
|
||||
static int ad9361_iodelay_set(struct axiadc_state *st, unsigned lane,
|
||||
unsigned val, bool tx)
|
||||
{
|
||||
if (tx) {
|
||||
if (ADI_AXI_PCORE_VER_MAJOR(st->pcore_version) > 8)
|
||||
axiadc_write(st, 0x4000 + ADI_REG_DELAY(lane), val);
|
||||
else
|
||||
return -ENODEV;
|
||||
} else {
|
||||
axiadc_idelay_set(st, lane, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad9361_midscale_iodelay(struct ad9361_rf_phy *phy, bool tx)
|
||||
{
|
||||
struct axiadc_converter *conv = spi_get_drvdata(phy->spi);
|
||||
struct axiadc_state *st = iio_priv(conv->indio_dev);
|
||||
int ret = 0, i;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
ret |= ad9361_iodelay_set(st, i, 15, tx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad9361_dig_tune_iodelay(struct ad9361_rf_phy *phy, bool tx)
|
||||
{
|
||||
struct axiadc_converter *conv = spi_get_drvdata(phy->spi);
|
||||
struct axiadc_state *st = iio_priv(conv->indio_dev);
|
||||
int i, j;
|
||||
u32 s0, c0;
|
||||
u8 field[32];
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
for (j = 0; j < 32; j++) {
|
||||
ad9361_iodelay_set(st, i, j, tx);
|
||||
mdelay(1);
|
||||
field[j] = ad9361_check_pn(conv, tx, 10);
|
||||
}
|
||||
|
||||
c0 = ad9361_find_opt(&field[0], 32, &s0);
|
||||
ad9361_iodelay_set(st, i, s0 + c0 / 2, tx);
|
||||
|
||||
dev_info(&phy->spi->dev,
|
||||
"%s Lane %d, window cnt %d , start %d, IODELAY set to %d\n",
|
||||
tx ? "TX" :"RX", i , c0, s0, s0 + c0 / 2);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ad9361_dig_tune_verbose_print(struct ad9361_rf_phy *phy,
|
||||
u8 field[][16], bool tx,
|
||||
int sel_clk, int sel_data)
|
||||
{
|
||||
int i, j;
|
||||
char c;
|
||||
|
||||
pr_info("SAMPL CLK: %lu tuning: %s\n",
|
||||
clk_get_rate(phy->clks[RX_SAMPL_CLK]), tx ? "TX" : "RX");
|
||||
pr_info(" ");
|
||||
for (i = 0; i < 16; i++)
|
||||
pr_cont("%x:", i);
|
||||
pr_cont("\n");
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
pr_info("%x:", i);
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (field[i][j])
|
||||
c = '#';
|
||||
else if ((i == 0 && j == sel_data) ||
|
||||
(i == 1 && j == sel_clk))
|
||||
c = 'O';
|
||||
else
|
||||
c = 'o';
|
||||
pr_cont("%c ", c);
|
||||
}
|
||||
pr_cont("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int ad9361_dig_tune_delay(struct ad9361_rf_phy *phy,
|
||||
unsigned long max_freq,
|
||||
enum dig_tune_flags flags, bool tx)
|
||||
{
|
||||
//static const unsigned int rates[3] = {25000000U, 40000000U, 61440000U}; //some low end FPGA, such as z7020, lvds ADC interface seems not stable enough to support 61.44Msps
|
||||
static const unsigned int rates[3] = {25000000U, 40000000U, 40000000U};
|
||||
struct axiadc_converter *conv = spi_get_drvdata(phy->spi);
|
||||
unsigned int s0, s1, c0, c1;
|
||||
unsigned int i, j, r;
|
||||
bool half_data_rate;
|
||||
u8 field[2][16];
|
||||
|
||||
if (ad9361_uses_lvds_mode(phy) || !ad9361_uses_rx2tx2(phy))
|
||||
half_data_rate = false;
|
||||
else
|
||||
half_data_rate = true;
|
||||
|
||||
memset(field, 0, 32);
|
||||
for (r = 0; r < (max_freq ? ARRAY_SIZE(rates) : 1); r++) {
|
||||
if (max_freq)
|
||||
ad9361_set_trx_clock_chain_freq(phy,
|
||||
half_data_rate ? rates[r] / 2 : rates[r]);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
/*
|
||||
* i == 0: clock delay = 0, data delay from 0 to 15
|
||||
* i == 1: clock delay = 15, data delay from 15 to 0
|
||||
*/
|
||||
ad9361_set_intf_delay(phy, tx, i ? 15 : 0,
|
||||
i ? 15 - j : j, j == 0);
|
||||
field[i][j] |= ad9361_check_pn(conv, tx, 4);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & BE_MOREVERBOSE) && max_freq) {
|
||||
ad9361_dig_tune_verbose_print(phy, field, tx, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
c0 = ad9361_find_opt(&field[0][0], 16, &s0);
|
||||
c1 = ad9361_find_opt(&field[1][0], 16, &s1);
|
||||
|
||||
if (!c0 && !c1) {
|
||||
ad9361_dig_tune_verbose_print(phy, field, tx, -1, -1);
|
||||
dev_err(&phy->spi->dev, "%s: Tuning %s FAILED!", __func__,
|
||||
tx ? "TX" : "RX");
|
||||
return -EIO;
|
||||
} else if (flags & BE_VERBOSE) {
|
||||
ad9361_dig_tune_verbose_print(phy, field, tx,
|
||||
c1 > c0 ? (s1 + c1 / 2) : -1,
|
||||
c1 > c0 ? -1 : (s0 + c0 / 2));
|
||||
}
|
||||
|
||||
if (c1 > c0)
|
||||
ad9361_set_intf_delay(phy, tx, s1 + c1 / 2, 0, true);
|
||||
else
|
||||
ad9361_set_intf_delay(phy, tx, 0, s0 + c0 / 2, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad9361_dig_tune_rx(struct ad9361_rf_phy *phy, unsigned long max_freq,
|
||||
enum dig_tune_flags flags)
|
||||
{
|
||||
struct axiadc_converter *conv = spi_get_drvdata(phy->spi);
|
||||
struct axiadc_state *st = iio_priv(conv->indio_dev);
|
||||
int ret;
|
||||
|
||||
ad9361_bist_loopback(phy, 0);
|
||||
ad9361_bist_prbs(phy, BIST_INJ_RX);
|
||||
|
||||
ret = ad9361_dig_tune_delay(phy, max_freq, flags, false);
|
||||
if (flags & DO_IDELAY)
|
||||
ad9361_dig_tune_iodelay(phy, false);
|
||||
|
||||
axiadc_write(st, ADI_REG_RSTN, ADI_MMCM_RSTN);
|
||||
axiadc_write(st, ADI_REG_RSTN, ADI_RSTN | ADI_MMCM_RSTN);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad9361_dig_tune_tx(struct ad9361_rf_phy *phy, unsigned long max_freq,
|
||||
enum dig_tune_flags flags)
|
||||
{
|
||||
struct axiadc_converter *conv = spi_get_drvdata(phy->spi);
|
||||
struct axiadc_state *st = iio_priv(conv->indio_dev);
|
||||
u32 saved_dsel[4], saved_chan_ctrl6[4], saved_chan_ctrl0[4];
|
||||
unsigned int chan, num_chan;
|
||||
unsigned int hdl_dac_version;
|
||||
u32 tmp, saved = 0;
|
||||
int ret;
|
||||
|
||||
num_chan = ad9361_num_phy_chan(conv);
|
||||
hdl_dac_version = axiadc_read(st, 0x4000);
|
||||
|
||||
ad9361_bist_prbs(phy, BIST_DISABLE);
|
||||
ad9361_bist_loopback(phy, 1);
|
||||
axiadc_write(st, 0x4000 + ADI_REG_RSTN, ADI_RSTN | ADI_MMCM_RSTN);
|
||||
|
||||
for (chan = 0; chan < num_chan; chan++) {
|
||||
saved_chan_ctrl0[chan] = axiadc_read(st, ADI_REG_CHAN_CNTRL(chan));
|
||||
axiadc_write(st, ADI_REG_CHAN_CNTRL(chan),
|
||||
ADI_FORMAT_SIGNEXT | ADI_FORMAT_ENABLE |
|
||||
ADI_ENABLE | ADI_IQCOR_ENB);
|
||||
axiadc_set_pnsel(st, chan, ADC_PN_CUSTOM);
|
||||
saved_chan_ctrl6[chan] = axiadc_read(st, 0x4414 + (chan) * 0x40);
|
||||
if (ADI_AXI_PCORE_VER_MAJOR(hdl_dac_version) > 7) {
|
||||
saved_dsel[chan] = axiadc_read(st, 0x4418 + (chan) * 0x40);
|
||||
axiadc_write(st, 0x4418 + (chan) * 0x40, 9);
|
||||
axiadc_write(st, 0x4414 + (chan) * 0x40, 0); /* !IQCOR_ENB */
|
||||
axiadc_write(st, 0x4044, 1);
|
||||
} else {
|
||||
axiadc_write(st, 0x4414 + (chan) * 0x40, 1); /* DAC_PN_ENB */
|
||||
}
|
||||
}
|
||||
if (ADI_AXI_PCORE_VER_MAJOR(hdl_dac_version) < 8) {
|
||||
saved = tmp = axiadc_read(st, 0x4048);
|
||||
tmp &= ~0xF;
|
||||
tmp |= 1;
|
||||
axiadc_write(st, 0x4048, tmp);
|
||||
}
|
||||
|
||||
ret = ad9361_dig_tune_delay(phy, max_freq, flags, true);
|
||||
if (flags & DO_ODELAY)
|
||||
ad9361_dig_tune_iodelay(phy, true);
|
||||
|
||||
if (ADI_AXI_PCORE_VER_MAJOR(hdl_dac_version) < 8)
|
||||
axiadc_write(st, 0x4048, saved);
|
||||
|
||||
for (chan = 0; chan < num_chan; chan++) {
|
||||
axiadc_write(st, ADI_REG_CHAN_CNTRL(chan),
|
||||
saved_chan_ctrl0[chan]);
|
||||
axiadc_set_pnsel(st, chan, ADC_PN9);
|
||||
if (ADI_AXI_PCORE_VER_MAJOR(hdl_dac_version) > 7) {
|
||||
axiadc_write(st, 0x4418 + chan * 0x40,
|
||||
saved_dsel[chan]);
|
||||
axiadc_write(st, 0x4044, 1);
|
||||
}
|
||||
|
||||
axiadc_write(st, 0x4414 + chan * 0x40, saved_chan_ctrl6[chan]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ad9361_dig_tune(struct ad9361_rf_phy *phy, unsigned long max_freq,
|
||||
enum dig_tune_flags flags)
|
||||
{
|
||||
struct axiadc_converter *conv = spi_get_drvdata(phy->spi);
|
||||
struct ad9361_dig_tune_data data;
|
||||
struct axiadc_state *st;
|
||||
bool restore = false;
|
||||
int ret = 0;
|
||||
|
||||
if (!conv)
|
||||
return -ENODEV;
|
||||
|
||||
ret = ad9361_get_dig_tune_data(phy, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_dbg(&phy->spi->dev, "%s: freq %lu flags 0x%X\n", __func__,
|
||||
max_freq, flags);
|
||||
|
||||
st = iio_priv(conv->indio_dev);
|
||||
|
||||
if ((data.skip_mode == SKIP_ALL) ||
|
||||
(flags & RESTORE_DEFAULT)) {
|
||||
/* skip completely and use defaults */
|
||||
restore = true;
|
||||
} else {
|
||||
/* Mute TX, we don't want to transmit the PRBS */
|
||||
ad9361_tx_mute(phy, 1);
|
||||
|
||||
ad9361_ensm_mode_disable_pinctrl(phy);
|
||||
|
||||
if (flags & DO_IDELAY)
|
||||
ad9361_midscale_iodelay(phy, false);
|
||||
|
||||
if (flags & DO_ODELAY)
|
||||
ad9361_midscale_iodelay(phy, true);
|
||||
|
||||
ret = ad9361_dig_tune_rx(phy, max_freq, flags);
|
||||
if (ret == 0 && (data.skip_mode == TUNE_RX_TX))
|
||||
ret = ad9361_dig_tune_tx(phy, max_freq, flags);
|
||||
|
||||
ad9361_bist_loopback(phy, data.bist_loopback_mode);
|
||||
ad9361_write_bist_reg(phy, data.bist_config);
|
||||
|
||||
if (ret == -EIO)
|
||||
restore = true;
|
||||
if (!max_freq)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (restore) {
|
||||
ad9361_ensm_force_state(phy, ENSM_STATE_ALERT);
|
||||
ad9361_write_clock_data_delays(phy);
|
||||
} else if (!(flags & SKIP_STORE_RESULT)) {
|
||||
ad9361_read_clock_data_delays(phy);
|
||||
}
|
||||
|
||||
ad9361_ensm_mode_restore_pinctrl(phy);
|
||||
ad9361_ensm_restore_state(phy, data.ensm_state);
|
||||
|
||||
axiadc_write(st, ADI_REG_RSTN, ADI_MMCM_RSTN);
|
||||
axiadc_write(st, ADI_REG_RSTN, ADI_RSTN | ADI_MMCM_RSTN);
|
||||
|
||||
ad9361_tx_mute(phy, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_dig_tune);
|
||||
|
||||
static int ad9361_post_setup(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct axiadc_state *st = iio_priv(indio_dev);
|
||||
struct axiadc_converter *conv = iio_device_get_drvdata(indio_dev);
|
||||
struct ad9361_rf_phy *phy = conv->phy;
|
||||
bool rx2tx2 = ad9361_uses_rx2tx2(phy);
|
||||
unsigned tmp, num_chan, flags;
|
||||
int i, ret;
|
||||
|
||||
num_chan = ad9361_num_phy_chan(conv);
|
||||
|
||||
conv->indio_dev = indio_dev;
|
||||
axiadc_write(st, ADI_REG_CNTRL, rx2tx2 ? 0 : ADI_R1_MODE);
|
||||
tmp = axiadc_read(st, 0x4048);
|
||||
|
||||
if (!rx2tx2) {
|
||||
axiadc_write(st, 0x4048, tmp | BIT(5)); /* R1_MODE */
|
||||
axiadc_write(st, 0x404c,
|
||||
ad9361_uses_lvds_mode(phy) ? 1 : 0); /* RATE */
|
||||
} else {
|
||||
tmp &= ~BIT(5);
|
||||
axiadc_write(st, 0x4048, tmp);
|
||||
axiadc_write(st, 0x404c,
|
||||
ad9361_uses_lvds_mode(phy) ? 3 : 1); /* RATE */
|
||||
}
|
||||
|
||||
for (i = 0; i < num_chan; i++) {
|
||||
axiadc_write(st, ADI_REG_CHAN_CNTRL_1(i),
|
||||
ADI_DCFILT_OFFSET(0));
|
||||
axiadc_write(st, ADI_REG_CHAN_CNTRL_2(i),
|
||||
(i & 1) ? 0x00004000 : 0x40000000);
|
||||
axiadc_write(st, ADI_REG_CHAN_CNTRL(i),
|
||||
ADI_FORMAT_SIGNEXT | ADI_FORMAT_ENABLE |
|
||||
ADI_ENABLE | ADI_IQCOR_ENB);
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
|
||||
ret = ad9361_dig_tune(phy, (axiadc_read(st, ADI_AXI_REG_ID)) ?
|
||||
0 : 61440000, flags);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
if (flags & (DO_IDELAY | DO_ODELAY)) {
|
||||
ret = ad9361_dig_tune(phy, (axiadc_read(st, ADI_AXI_REG_ID)) ?
|
||||
0 : 61440000, flags & BE_VERBOSE);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = ad9361_set_trx_clock_chain_default(phy);
|
||||
|
||||
ad9361_ensm_force_state(phy, ENSM_STATE_ALERT);
|
||||
ad9361_ensm_restore_prev_state(phy);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
spi_set_drvdata(phy->spi, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ad9361_register_axi_converter(struct ad9361_rf_phy *phy)
|
||||
{
|
||||
struct axiadc_converter *conv;
|
||||
struct spi_device *spi = phy->spi;
|
||||
int ret;
|
||||
|
||||
conv = devm_kzalloc(&spi->dev, sizeof(*conv), GFP_KERNEL);
|
||||
if (conv == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
conv->id = ad9361_spi_read(spi, REG_PRODUCT_ID) & PRODUCT_ID_MASK;
|
||||
if (conv->id != PRODUCT_ID_9361) {
|
||||
dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", conv->id);
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
conv->chip_info = &axiadc_chip_info_tbl[
|
||||
(spi_get_device_id(spi)->driver_data == ID_AD9361_2) ?
|
||||
ID_AD9361_2 : ad9361_uses_rx2tx2(phy) ? ID_AD9361 : ID_AD9364];
|
||||
conv->write_raw = ad9361_write_raw;
|
||||
conv->read_raw = ad9361_read_raw;
|
||||
conv->post_setup = ad9361_post_setup;
|
||||
conv->spi = spi;
|
||||
conv->phy = phy;
|
||||
|
||||
conv->clk = phy->clks[RX_SAMPL_CLK];
|
||||
conv->adc_clk = clk_get_rate(conv->clk);
|
||||
|
||||
spi_set_drvdata(spi, conv); /* Take care here */
|
||||
|
||||
return 0;
|
||||
out:
|
||||
spi_set_drvdata(spi, NULL);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_register_axi_converter);
|
||||
|
||||
struct ad9361_rf_phy* ad9361_spi_to_phy(struct spi_device *spi)
|
||||
{
|
||||
struct axiadc_converter *conv = spi_get_drvdata(spi);
|
||||
return conv->phy;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_spi_to_phy);
|
||||
|
||||
#else /* CONFIG_CF_AXI_ADC */
|
||||
|
||||
int ad9361_dig_tune(struct ad9361_rf_phy *phy, unsigned long max_freq,
|
||||
enum dig_tune_flags flags)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_dig_tune);
|
||||
|
||||
ssize_t ad9361_dig_interface_timing_analysis(struct ad9361_rf_phy *phy,
|
||||
char *buf, unsigned buflen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_dig_interface_timing_analysis);
|
||||
|
||||
int ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_hdl_loopback);
|
||||
|
||||
int ad9361_register_axi_converter(struct ad9361_rf_phy *phy)
|
||||
{
|
||||
struct spi_device *spi = phy->spi;
|
||||
spi_set_drvdata(spi, phy); /* Take care here */
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_register_axi_converter);
|
||||
|
||||
struct ad9361_rf_phy* ad9361_spi_to_phy(struct spi_device *spi)
|
||||
{
|
||||
return spi_get_drvdata(spi);
|
||||
}
|
||||
EXPORT_SYMBOL(ad9361_spi_to_phy);
|
||||
|
||||
#endif /* CONFIG_CF_AXI_ADC */
|
@ -1,504 +0,0 @@
|
||||
/*
|
||||
* AD9361 - Private definitions to be used only in the ad9361.c fileer
|
||||
* SPDX-FileCopyrightText: Copyright 2013-2018 Analog Devices Inc.
|
||||
* Modified by Xianjun jiao
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef IIO_AD9361_PRIVATE_H_
|
||||
#define IIO_AD9361_PRIVATE_H_
|
||||
|
||||
#ifndef IIO_AD9361_USE_PRIVATE_H_
|
||||
#error "Please do not include ad9361_private.h; use ad9361.h instead"
|
||||
#endif
|
||||
|
||||
#include "ad9361.h"
|
||||
|
||||
/*
|
||||
* Driver
|
||||
*/
|
||||
|
||||
enum rx_gain_table_type {
|
||||
RXGAIN_FULL_TBL,
|
||||
RXGAIN_SPLIT_TBL,
|
||||
};
|
||||
|
||||
enum rx_gain_table_name {
|
||||
TBL_200_1300_MHZ,
|
||||
TBL_1300_4000_MHZ,
|
||||
TBL_4000_6000_MHZ,
|
||||
RXGAIN_TBLS_END,
|
||||
};
|
||||
|
||||
enum fir_dest {
|
||||
FIR_TX1 = 0x01,
|
||||
FIR_TX2 = 0x02,
|
||||
FIR_TX1_TX2 = 0x03,
|
||||
FIR_RX1 = 0x81,
|
||||
FIR_RX2 = 0x82,
|
||||
FIR_RX1_RX2 = 0x83,
|
||||
FIR_IS_RX = 0x80,
|
||||
};
|
||||
|
||||
struct rf_gain_ctrl {
|
||||
u32 ant;
|
||||
u8 mode;
|
||||
};
|
||||
|
||||
enum rf_gain_ctrl_mode {
|
||||
RF_GAIN_MGC,
|
||||
RF_GAIN_FASTATTACK_AGC,
|
||||
RF_GAIN_SLOWATTACK_AGC,
|
||||
RF_GAIN_HYBRID_AGC
|
||||
};
|
||||
|
||||
enum f_agc_target_gain_index_type {
|
||||
MAX_GAIN,
|
||||
SET_GAIN,
|
||||
OPTIMIZED_GAIN,
|
||||
NO_GAIN_CHANGE,
|
||||
};
|
||||
|
||||
struct gain_control {
|
||||
enum rf_gain_ctrl_mode rx1_mode;
|
||||
enum rf_gain_ctrl_mode rx2_mode;
|
||||
|
||||
/* Common */
|
||||
u8 adc_ovr_sample_size; /* 1..8 Sum x samples, AGC_CONFIG_3 */
|
||||
u8 adc_small_overload_thresh; /* 0..255, 0x105 */
|
||||
u8 adc_large_overload_thresh; /* 0..255, 0x104 */
|
||||
|
||||
u16 lmt_overload_high_thresh; /* 16..800 mV, 0x107 */
|
||||
u16 lmt_overload_low_thresh; /* 16..800 mV, 0x108 */
|
||||
u16 dec_pow_measuremnt_duration; /* Samples, 0x15C */
|
||||
u8 low_power_thresh; /* -64..0 dBFS, 0x114 */
|
||||
bool use_rx_fir_out_for_dec_pwr_meas; /* clears 0x15C:6 USE_HB1_OUT_FOR_DEC_PWR_MEAS */
|
||||
|
||||
bool dig_gain_en; /* should be turned off, since ADI GT doesn't use dig gain */
|
||||
u8 max_dig_gain; /* 0..31 */
|
||||
|
||||
/* MGC */
|
||||
bool mgc_rx1_ctrl_inp_en; /* Enables Pin control on RX1 default SPI ctrl */
|
||||
bool mgc_rx2_ctrl_inp_en; /* Enables Pin control on RX2 default SPI ctrl */
|
||||
|
||||
u8 mgc_inc_gain_step; /* 1..8 */
|
||||
u8 mgc_dec_gain_step; /* 1..8 */
|
||||
u8 mgc_split_table_ctrl_inp_gain_mode; /* 0=AGC determine this, 1=only in LPF, 2=only in LMT */
|
||||
|
||||
/* AGC */
|
||||
u8 agc_attack_delay_extra_margin_us; /* 0..31 us */
|
||||
|
||||
u8 agc_outer_thresh_high;
|
||||
u8 agc_outer_thresh_high_dec_steps;
|
||||
u8 agc_inner_thresh_high;
|
||||
u8 agc_inner_thresh_high_dec_steps;
|
||||
u8 agc_inner_thresh_low;
|
||||
u8 agc_inner_thresh_low_inc_steps;
|
||||
u8 agc_outer_thresh_low;
|
||||
u8 agc_outer_thresh_low_inc_steps;
|
||||
|
||||
u8 adc_small_overload_exceed_counter; /* 0..15, 0x122 */
|
||||
u8 adc_large_overload_exceed_counter; /* 0..15, 0x122 */
|
||||
u8 adc_large_overload_inc_steps; /* 0..15, 0x106 */
|
||||
|
||||
bool adc_lmt_small_overload_prevent_gain_inc; /* 0x120 */
|
||||
|
||||
u8 lmt_overload_large_exceed_counter; /* 0..15, 0x121 */
|
||||
u8 lmt_overload_small_exceed_counter; /* 0..15, 0x121 */
|
||||
u8 lmt_overload_large_inc_steps; /* 0..7, 0x121 */
|
||||
|
||||
u8 dig_saturation_exceed_counter; /* 0..15, 0x128 */
|
||||
u8 dig_gain_step_size; /* 1..8, 0x100 */
|
||||
bool sync_for_gain_counter_en; /* 0x128:4 !Hybrid */
|
||||
|
||||
u32 gain_update_interval_us; /* in us */
|
||||
bool immed_gain_change_if_large_adc_overload; /* 0x123:3 */
|
||||
bool immed_gain_change_if_large_lmt_overload; /* 0x123:7 */
|
||||
|
||||
/*
|
||||
* Fast AGC
|
||||
*/
|
||||
u32 f_agc_dec_pow_measuremnt_duration; /* Samples, 0x15C */
|
||||
u32 f_agc_state_wait_time_ns; /* 0x117 0..31 RX samples -> time_ns */
|
||||
/* Fast AGC - Low Power */
|
||||
bool f_agc_allow_agc_gain_increase; /* 0x110:1 */
|
||||
u8 f_agc_lp_thresh_increment_time; /* 0x11B RX samples */
|
||||
u8 f_agc_lp_thresh_increment_steps; /* 0x117 1..8 */
|
||||
|
||||
/* Fast AGC - Lock Level */
|
||||
u8 f_agc_lock_level; /* NOT USED: 0x101 0..-127 dBFS same as agc_inner_thresh_high */
|
||||
bool f_agc_lock_level_lmt_gain_increase_en; /* 0x111:6 */
|
||||
u8 f_agc_lock_level_gain_increase_upper_limit; /* 0x118 0..63 */
|
||||
/* Fast AGC - Peak Detectors and Final Settling */
|
||||
u8 f_agc_lpf_final_settling_steps; /* 0x112:6 0..3 (Post Lock Level Step)*/
|
||||
u8 f_agc_lmt_final_settling_steps; /* 0x113:6 0..3 (Post Lock Level Step)*/
|
||||
u8 f_agc_final_overrange_count; /* 0x116:5 0..7 */
|
||||
/* Fast AGC - Final Power Test */
|
||||
bool f_agc_gain_increase_after_gain_lock_en; /* 0x110:7 */
|
||||
/* Fast AGC - Unlocking the Gain */
|
||||
/* 0 = MAX Gain, 1 = Set Gain, 2 = Optimized Gain */
|
||||
enum f_agc_target_gain_index_type f_agc_gain_index_type_after_exit_rx_mode; /* 0x110:[4,2] */
|
||||
bool f_agc_use_last_lock_level_for_set_gain_en; /* 0x111:7 */
|
||||
u8 f_agc_optimized_gain_offset; /*0x116 0..15 steps */
|
||||
bool f_agc_rst_gla_stronger_sig_thresh_exceeded_en; /* 0x110:~6 */
|
||||
u8 f_agc_rst_gla_stronger_sig_thresh_above_ll; /*0x113 0..63 dbFS */
|
||||
bool f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en; /* 0x110:6 */
|
||||
bool f_agc_rst_gla_engergy_lost_goto_optim_gain_en; /* 0x110:6 */
|
||||
u8 f_agc_rst_gla_engergy_lost_sig_thresh_below_ll; /* 0x112:6 */
|
||||
u8 f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt; /* 0x119 0..63 RX samples */
|
||||
bool f_agc_rst_gla_large_adc_overload_en; /*0x110:~1 and 0x114:~7 */
|
||||
bool f_agc_rst_gla_large_lmt_overload_en; /*0x110:~1 */
|
||||
bool f_agc_rst_gla_en_agc_pulled_high_en;
|
||||
/* 0 = Max Gain, 1 = Set Gain, 2 = Optimized Gain, 3 = No Gain Change */
|
||||
|
||||
enum f_agc_target_gain_index_type f_agc_rst_gla_if_en_agc_pulled_high_mode; /* 0x0FB, 0x111 */
|
||||
u8 f_agc_power_measurement_duration_in_state5; /* 0x109, 0x10a RX samples 0..524288*/
|
||||
u8 f_agc_large_overload_inc_steps; /* 0x106 [D6:D4] 0..7 */
|
||||
|
||||
};
|
||||
|
||||
struct auxdac_control {
|
||||
u16 dac1_default_value;
|
||||
u16 dac2_default_value;
|
||||
|
||||
bool auxdac_manual_mode_en;
|
||||
|
||||
bool dac1_in_rx_en;
|
||||
bool dac1_in_tx_en;
|
||||
bool dac1_in_alert_en;
|
||||
|
||||
bool dac2_in_rx_en;
|
||||
bool dac2_in_tx_en;
|
||||
bool dac2_in_alert_en;
|
||||
|
||||
u8 dac1_rx_delay_us;
|
||||
u8 dac1_tx_delay_us;
|
||||
u8 dac2_rx_delay_us;
|
||||
u8 dac2_tx_delay_us;
|
||||
};
|
||||
|
||||
#if 0
|
||||
enum rssi_restart_mode {
|
||||
AGC_IN_FAST_ATTACK_MODE_LOCKS_THE_GAIN,
|
||||
EN_AGC_PIN_IS_PULLED_HIGH,
|
||||
ENTERS_RX_MODE,
|
||||
GAIN_CHANGE_OCCURS,
|
||||
SPI_WRITE_TO_REGISTER,
|
||||
GAIN_CHANGE_OCCURS_OR_EN_AGC_PIN_PULLED_HIGH,
|
||||
};
|
||||
|
||||
struct rssi_control {
|
||||
enum rssi_restart_mode restart_mode;
|
||||
bool rssi_unit_is_rx_samples; /* default unit is time */
|
||||
u32 rssi_delay;
|
||||
u32 rssi_wait;
|
||||
u32 rssi_duration;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct rx_gain_info {
|
||||
enum rx_gain_table_type tbl_type;
|
||||
int starting_gain_db;
|
||||
int max_gain_db;
|
||||
int gain_step_db;
|
||||
int max_idx;
|
||||
int idx_step_offset;
|
||||
};
|
||||
|
||||
struct port_control {
|
||||
u8 pp_conf[3];
|
||||
u8 rx_clk_data_delay;
|
||||
u8 tx_clk_data_delay;
|
||||
u8 digital_io_ctrl;
|
||||
u8 lvds_bias_ctrl;
|
||||
u8 lvds_invert[2];
|
||||
};
|
||||
|
||||
#if 0
|
||||
struct ctrl_outs_control {
|
||||
u8 index;
|
||||
u8 en_mask;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct elna_control {
|
||||
u16 gain_mdB;
|
||||
u16 bypass_loss_mdB;
|
||||
u32 settling_delay_ns;
|
||||
bool elna_1_control_en; /* GPO0 */
|
||||
bool elna_2_control_en; /* GPO1 */
|
||||
bool elna_in_gaintable_all_index_en;
|
||||
};
|
||||
|
||||
struct auxadc_control {
|
||||
s8 offset;
|
||||
u32 temp_time_inteval_ms;
|
||||
u32 temp_sensor_decimation;
|
||||
bool periodic_temp_measuremnt;
|
||||
u32 auxadc_clock_rate;
|
||||
u32 auxadc_decimation;
|
||||
};
|
||||
|
||||
struct gpo_control {
|
||||
u32 gpo_manual_mode_enable_mask;
|
||||
bool gpo_manual_mode_en;
|
||||
bool gpo0_inactive_state_high_en;
|
||||
bool gpo1_inactive_state_high_en;
|
||||
bool gpo2_inactive_state_high_en;
|
||||
bool gpo3_inactive_state_high_en;
|
||||
bool gpo0_slave_rx_en;
|
||||
bool gpo0_slave_tx_en;
|
||||
bool gpo1_slave_rx_en;
|
||||
bool gpo1_slave_tx_en;
|
||||
bool gpo2_slave_rx_en;
|
||||
bool gpo2_slave_tx_en;
|
||||
bool gpo3_slave_rx_en;
|
||||
bool gpo3_slave_tx_en;
|
||||
u8 gpo0_rx_delay_us;
|
||||
u8 gpo0_tx_delay_us;
|
||||
u8 gpo1_rx_delay_us;
|
||||
u8 gpo1_tx_delay_us;
|
||||
u8 gpo2_rx_delay_us;
|
||||
u8 gpo2_tx_delay_us;
|
||||
u8 gpo3_rx_delay_us;
|
||||
u8 gpo3_tx_delay_us;
|
||||
};
|
||||
|
||||
struct tx_monitor_control {
|
||||
bool tx_mon_track_en;
|
||||
bool one_shot_mode_en;
|
||||
u32 low_high_gain_threshold_mdB;
|
||||
u8 low_gain_dB;
|
||||
u8 high_gain_dB;
|
||||
u16 tx_mon_delay;
|
||||
u16 tx_mon_duration;
|
||||
u8 tx1_mon_front_end_gain;
|
||||
u8 tx2_mon_front_end_gain;
|
||||
u8 tx1_mon_lo_cm;
|
||||
u8 tx2_mon_lo_cm;
|
||||
};
|
||||
|
||||
enum ad9361_pdata_rx_freq {
|
||||
BBPLL_FREQ,
|
||||
ADC_FREQ,
|
||||
R2_FREQ,
|
||||
R1_FREQ,
|
||||
CLKRF_FREQ,
|
||||
RX_SAMPL_FREQ,
|
||||
NUM_RX_CLOCKS,
|
||||
};
|
||||
|
||||
enum ad9361_pdata_tx_freq {
|
||||
IGNORE,
|
||||
DAC_FREQ,
|
||||
T2_FREQ,
|
||||
T1_FREQ,
|
||||
CLKTF_FREQ,
|
||||
TX_SAMPL_FREQ,
|
||||
NUM_TX_CLOCKS,
|
||||
};
|
||||
|
||||
enum ad9361_clkout {
|
||||
CLKOUT_DISABLE,
|
||||
BUFFERED_XTALN_DCXO,
|
||||
ADC_CLK_DIV_2,
|
||||
ADC_CLK_DIV_3,
|
||||
ADC_CLK_DIV_4,
|
||||
ADC_CLK_DIV_8,
|
||||
ADC_CLK_DIV_16,
|
||||
};
|
||||
|
||||
enum synth_pd_ctrl {
|
||||
LO_DONTCARE,
|
||||
LO_OFF,
|
||||
LO_ON,
|
||||
};
|
||||
|
||||
struct ad9361_phy_platform_data {
|
||||
bool rx2tx2;
|
||||
bool fdd;
|
||||
bool fdd_independent_mode;
|
||||
bool split_gt;
|
||||
bool use_extclk;
|
||||
bool ensm_pin_pulse_mode;
|
||||
bool ensm_pin_ctrl;
|
||||
bool debug_mode;
|
||||
bool tdd_use_dual_synth;
|
||||
bool tdd_skip_vco_cal;
|
||||
bool use_ext_rx_lo;
|
||||
bool use_ext_tx_lo;
|
||||
bool rx1rx2_phase_inversion_en;
|
||||
bool qec_tracking_slow_mode_en;
|
||||
bool dig_interface_tune_fir_disable;
|
||||
bool lo_powerdown_managed_en;
|
||||
u8 dc_offset_update_events;
|
||||
u8 dc_offset_attenuation_high;
|
||||
u8 dc_offset_attenuation_low;
|
||||
u8 rf_dc_offset_count_high;
|
||||
u8 rf_dc_offset_count_low;
|
||||
u8 dig_interface_tune_skipmode;
|
||||
u32 dcxo_coarse;
|
||||
u32 dcxo_fine;
|
||||
bool rf_rx_input_sel_lock;
|
||||
bool rf_tx_output_sel_lock;
|
||||
u32 rx1tx1_mode_use_rx_num;
|
||||
u32 rx1tx1_mode_use_tx_num;
|
||||
unsigned long rx_path_clks[NUM_RX_CLOCKS];
|
||||
unsigned long tx_path_clks[NUM_TX_CLOCKS];
|
||||
u32 trx_synth_max_fref;
|
||||
u64 rx_synth_freq;
|
||||
u64 tx_synth_freq;
|
||||
u32 rf_rx_bandwidth_Hz;
|
||||
u32 rf_tx_bandwidth_Hz;
|
||||
int tx_atten;
|
||||
bool update_tx_gain_via_alert;
|
||||
u32 rx_fastlock_delay_ns;
|
||||
u32 tx_fastlock_delay_ns;
|
||||
bool trx_fastlock_pinctrl_en[2];
|
||||
|
||||
enum ad9361_clkout ad9361_clkout_mode;
|
||||
|
||||
struct gain_control gain_ctrl;
|
||||
struct rssi_control rssi_ctrl;
|
||||
u32 rssi_lna_err_tbl[4];
|
||||
u32 rssi_mixer_err_tbl[16];
|
||||
u32 rssi_gain_step_calib_reg_val[5];
|
||||
bool rssi_skip_calib;
|
||||
struct port_control port_ctrl;
|
||||
struct ctrl_outs_control ctrl_outs_ctrl;
|
||||
struct elna_control elna_ctrl;
|
||||
struct auxadc_control auxadc_ctrl;
|
||||
struct auxdac_control auxdac_ctrl;
|
||||
struct gpo_control gpo_ctrl;
|
||||
struct tx_monitor_control txmon_ctrl;
|
||||
|
||||
struct gpio_desc *reset_gpio;
|
||||
/* MCS SYNC */
|
||||
struct gpio_desc *sync_gpio;
|
||||
struct gpio_desc *cal_sw1_gpio;
|
||||
struct gpio_desc *cal_sw2_gpio;
|
||||
|
||||
};
|
||||
|
||||
struct rf_rx_gain {
|
||||
u32 ant; /* Antenna number to read gain */
|
||||
s32 gain_db; /* gain value in dB */
|
||||
u32 fgt_lmt_index; /* Full Gain Table / LNA-MIXER-TIA gain index */
|
||||
u32 lmt_gain; /* LNA-MIXER-TIA gain in dB (Split GT mode only)*/
|
||||
u32 lpf_gain; /* Low pass filter gain in dB / index (Split GT mode only)*/
|
||||
u32 digital_gain; /* Digital gain in dB / index */
|
||||
/* Debug only */
|
||||
u32 lna_index; /* LNA Index (Split GT mode only) */
|
||||
u32 tia_index; /* TIA Index (Split GT mode only) */
|
||||
u32 mixer_index; /* MIXER Index (Split GT mode only) */
|
||||
|
||||
};
|
||||
#if 0
|
||||
struct rf_rssi {
|
||||
u32 ant; /* Antenna number for which RSSI is reported */
|
||||
u32 symbol; /* Runtime RSSI */
|
||||
u32 preamble; /* Initial RSSI */
|
||||
s32 multiplier; /* Multiplier to convert reported RSSI */
|
||||
u8 duration; /* Duration to be considered for measuring */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct SynthLUT {
|
||||
u16 VCO_MHz;
|
||||
u8 VCO_Output_Level;
|
||||
u8 VCO_Varactor;
|
||||
u8 VCO_Bias_Ref;
|
||||
u8 VCO_Bias_Tcf;
|
||||
u8 VCO_Cal_Offset;
|
||||
u8 VCO_Varactor_Reference;
|
||||
u8 Charge_Pump_Current;
|
||||
u8 LF_C2;
|
||||
u8 LF_C1;
|
||||
u8 LF_R1;
|
||||
u8 LF_C3;
|
||||
u8 LF_R3;
|
||||
};
|
||||
|
||||
#define SYNTH_LUT_SIZE 53
|
||||
|
||||
enum {
|
||||
LUT_FTDD_40,
|
||||
LUT_FTDD_60,
|
||||
LUT_FTDD_80,
|
||||
LUT_FTDD_ENT,
|
||||
};
|
||||
|
||||
struct ad9361_fastlock_entry {
|
||||
#define FASTLOOK_INIT 1
|
||||
u8 flags;
|
||||
u8 alc_orig;
|
||||
u8 alc_written;
|
||||
};
|
||||
|
||||
struct ad9361_fastlock {
|
||||
u8 save_profile;
|
||||
u8 current_profile[2];
|
||||
struct ad9361_fastlock_entry entry[2][8];
|
||||
};
|
||||
|
||||
struct ad9361_rf_phy_state {
|
||||
u8 prev_ensm_state;
|
||||
u8 curr_ensm_state;
|
||||
u8 cached_rx_rfpll_div;
|
||||
u8 cached_tx_rfpll_div;
|
||||
u8 cached_synth_pd[2];
|
||||
int tx_quad_lpf_tia_match;
|
||||
int current_table;
|
||||
int rx_sampl_freq_avail[3];
|
||||
int tx_sampl_freq_avail[3];
|
||||
int rx_gain_avail[3];
|
||||
|
||||
bool ensm_pin_ctl_en;
|
||||
|
||||
bool auto_cal_en;
|
||||
bool manual_tx_quad_cal_en;
|
||||
u64 last_tx_quad_cal_freq;
|
||||
u32 last_tx_quad_cal_phase;
|
||||
u64 current_tx_lo_freq;
|
||||
u64 current_rx_lo_freq;
|
||||
bool current_tx_use_tdd_table;
|
||||
bool current_rx_use_tdd_table;
|
||||
unsigned long current_rx_path_clks[NUM_RX_CLOCKS];
|
||||
unsigned long current_tx_path_clks[NUM_TX_CLOCKS];
|
||||
unsigned long flags;
|
||||
unsigned long cal_threshold_freq;
|
||||
u32 current_rx_bw_Hz;
|
||||
u32 current_tx_bw_Hz;
|
||||
u32 rxbbf_div;
|
||||
u32 rate_governor;
|
||||
bool bypass_rx_fir;
|
||||
bool bypass_tx_fir;
|
||||
bool rx_eq_2tx;
|
||||
bool filt_valid;
|
||||
unsigned long filt_rx_path_clks[NUM_RX_CLOCKS];
|
||||
unsigned long filt_tx_path_clks[NUM_TX_CLOCKS];
|
||||
u32 filt_rx_bw_Hz;
|
||||
u32 filt_tx_bw_Hz;
|
||||
u8 tx_fir_int;
|
||||
u8 tx_fir_ntaps;
|
||||
u8 rx_fir_dec;
|
||||
u8 rx_fir_ntaps;
|
||||
u8 agc_mode[2];
|
||||
bool rfdc_track_en;
|
||||
bool bbdc_track_en;
|
||||
bool quad_track_en;
|
||||
bool txmon_tdd_en;
|
||||
u16 auxdac1_value;
|
||||
u16 auxdac2_value;
|
||||
u32 tx1_atten_cached;
|
||||
u32 tx2_atten_cached;
|
||||
u8 bist_loopback_mode;
|
||||
u8 bist_config;
|
||||
u32 rf_rx_input_sel;
|
||||
u32 rf_tx_output_sel;
|
||||
|
||||
struct ad9361_fastlock fastlock;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,348 +0,0 @@
|
||||
/*
|
||||
* ADI-AIM ADI ADC Interface Module
|
||||
* SPDX-FileCopyrightText: Copyright 2012-2017 Analog Devices Inc.
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467
|
||||
*/
|
||||
|
||||
#ifndef ADI_AXI_ADC_H_
|
||||
#define ADI_AXI_ADC_H_
|
||||
|
||||
#include <linux/fpga/adi-axi-common.h>
|
||||
|
||||
/* ADC COMMON */
|
||||
|
||||
#define ADI_REG_CONFIG 0x000C
|
||||
#define ADI_IQCORRECTION_DISABLE (1 << 0)
|
||||
#define ADI_DCFILTER_DISABLE (1 << 1)
|
||||
#define ADI_DATAFORMAT_DISABLE (1 << 2)
|
||||
#define ADI_USERPORTS_DISABLE (1 << 3)
|
||||
#define ADI_MODE_1R1T (1 << 4)
|
||||
#define ADI_SCALECORRECTION_ONLY (1 << 5)
|
||||
#define ADI_CMOS_OR_LVDS_N (1 << 7)
|
||||
#define ADI_PPS_RECEIVER_ENABLE (1 << 8)
|
||||
|
||||
#define ADI_REG_RSTN 0x0040
|
||||
#define ADI_RSTN (1 << 0)
|
||||
#define ADI_MMCM_RSTN (1 << 1)
|
||||
|
||||
#define ADI_REG_CNTRL 0x0044
|
||||
#define ADI_R1_MODE (1 << 2)
|
||||
#define ADI_DDR_EDGESEL (1 << 1)
|
||||
#define ADI_PIN_MODE (1 << 0)
|
||||
|
||||
#define ADI_REG_CLK_FREQ 0x0054
|
||||
#define ADI_CLK_FREQ(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define ADI_TO_CLK_FREQ(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
|
||||
#define ADI_REG_CLK_RATIO 0x0058
|
||||
#define ADI_CLK_RATIO(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define ADI_TO_CLK_RATIO(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
|
||||
#define ADI_REG_STATUS 0x005C
|
||||
#define ADI_MUX_PN_ERR (1 << 3)
|
||||
#define ADI_MUX_PN_OOS (1 << 2)
|
||||
#define ADI_MUX_OVER_RANGE (1 << 1)
|
||||
#define ADI_STATUS (1 << 0)
|
||||
|
||||
#define ADI_REG_DELAY_CNTRL 0x0060 /* <= v8.0 */
|
||||
#define ADI_DELAY_SEL (1 << 17)
|
||||
#define ADI_DELAY_RWN (1 << 16)
|
||||
#define ADI_DELAY_ADDRESS(x) (((x) & 0xFF) << 8)
|
||||
#define ADI_TO_DELAY_ADDRESS(x) (((x) >> 8) & 0xFF)
|
||||
#define ADI_DELAY_WDATA(x) (((x) & 0x1F) << 0)
|
||||
#define ADI_TO_DELAY_WDATA(x) (((x) >> 0) & 0x1F)
|
||||
|
||||
#define ADI_REG_DELAY_STATUS 0x0064 /* <= v8.0 */
|
||||
#define ADI_DELAY_LOCKED (1 << 9)
|
||||
#define ADI_DELAY_STATUS (1 << 8)
|
||||
#define ADI_DELAY_RDATA(x) (((x) & 0x1F) << 0)
|
||||
#define ADI_TO_DELAY_RDATA(x) (((x) >> 0) & 0x1F)
|
||||
|
||||
#define ADI_REG_DRP_CNTRL 0x0070
|
||||
#define ADI_DRP_SEL (1 << 29)
|
||||
#define ADI_DRP_RWN (1 << 28)
|
||||
#define ADI_DRP_ADDRESS(x) (((x) & 0xFFF) << 16)
|
||||
#define ADI_TO_DRP_ADDRESS(x) (((x) >> 16) & 0xFFF)
|
||||
#define ADI_DRP_WDATA(x) (((x) & 0xFFFF) << 0)
|
||||
#define ADI_TO_DRP_WDATA(x) (((x) >> 0) & 0xFFFF)
|
||||
|
||||
#define ADI_REG_DRP_STATUS 0x0074
|
||||
#define ADI_DRP_STATUS (1 << 16)
|
||||
#define ADI_DRP_RDATA(x) (((x) & 0xFFFF) << 0)
|
||||
#define ADI_TO_DRP_RDATA(x) (((x) >> 0) & 0xFFFF)
|
||||
|
||||
#define ADI_REG_DMA_STATUS 0x0088
|
||||
#define ADI_DMA_OVF (1 << 2)
|
||||
#define ADI_DMA_UNF (1 << 1)
|
||||
#define ADI_DMA_STATUS (1 << 0)
|
||||
|
||||
#define ADI_REG_DMA_BUSWIDTH 0x008C
|
||||
#define ADI_DMA_BUSWIDTH(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define ADI_TO_DMA_BUSWIDTH(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
|
||||
#define ADI_REG_USR_CNTRL_1 0x00A0
|
||||
#define ADI_USR_CHANMAX(x) (((x) & 0xFF) << 0)
|
||||
#define ADI_TO_USR_CHANMAX(x) (((x) >> 0) & 0xFF)
|
||||
|
||||
#define ADI_REG_GP_CONTROL 0x00BC
|
||||
|
||||
#define ADI_REG_CLOCKS_PER_PPS 0x00C0
|
||||
#define ADI_REG_CLOCKS_PER_PPS_STATUS 0x00C4
|
||||
#define ADI_CLOCKS_PER_PPS_STAT_INVAL (1 << 0)
|
||||
|
||||
/* ADC CHANNEL */
|
||||
|
||||
#define ADI_REG_CHAN_CNTRL(c) (0x0400 + (c) * 0x40)
|
||||
#define ADI_PN_SEL (1 << 10) /* !v8.0 */
|
||||
#define ADI_IQCOR_ENB (1 << 9)
|
||||
#define ADI_DCFILT_ENB (1 << 8)
|
||||
#define ADI_FORMAT_SIGNEXT (1 << 6)
|
||||
#define ADI_FORMAT_TYPE (1 << 5)
|
||||
#define ADI_FORMAT_ENABLE (1 << 4)
|
||||
#define ADI_PN23_TYPE (1 << 1) /* !v8.0 */
|
||||
#define ADI_ENABLE (1 << 0)
|
||||
|
||||
#define ADI_REG_CHAN_STATUS(c) (0x0404 + (c) * 0x40)
|
||||
#define ADI_PN_ERR (1 << 2)
|
||||
#define ADI_PN_OOS (1 << 1)
|
||||
#define ADI_OVER_RANGE (1 << 0)
|
||||
|
||||
#define ADI_REG_CHAN_CNTRL_1(c) (0x0410 + (c) * 0x40)
|
||||
#define ADI_DCFILT_OFFSET(x) (((x) & 0xFFFF) << 16)
|
||||
#define ADI_TO_DCFILT_OFFSET(x) (((x) >> 16) & 0xFFFF)
|
||||
#define ADI_DCFILT_COEFF(x) (((x) & 0xFFFF) << 0)
|
||||
#define ADI_TO_DCFILT_COEFF(x) (((x) >> 0) & 0xFFFF)
|
||||
|
||||
#define ADI_REG_CHAN_CNTRL_2(c) (0x0414 + (c) * 0x40)
|
||||
#define ADI_IQCOR_COEFF_1(x) (((x) & 0xFFFF) << 16)
|
||||
#define ADI_TO_IQCOR_COEFF_1(x) (((x) >> 16) & 0xFFFF)
|
||||
#define ADI_IQCOR_COEFF_2(x) (((x) & 0xFFFF) << 0)
|
||||
#define ADI_TO_IQCOR_COEFF_2(x) (((x) >> 0) & 0xFFFF)
|
||||
|
||||
#define ADI_REG_CHAN_CNTRL_3(c) (0x0418 + (c) * 0x40) /* v8.0 */
|
||||
#define ADI_ADC_PN_SEL(x) (((x) & 0xF) << 16)
|
||||
#define ADI_TO_ADC_PN_SEL(x) (((x) >> 16) & 0xF)
|
||||
#define ADI_ADC_DATA_SEL(x) (((x) & 0xF) << 0)
|
||||
#define ADI_TO_ADC_DATA_SEL(x) (((x) >> 0) & 0xF)
|
||||
|
||||
enum adc_pn_sel {
|
||||
ADC_PN9 = 0,
|
||||
ADC_PN23A = 1,
|
||||
ADC_PN7 = 4,
|
||||
ADC_PN15 = 5,
|
||||
ADC_PN23 = 6,
|
||||
ADC_PN31 = 7,
|
||||
ADC_PN_CUSTOM = 9,
|
||||
ADC_PN_OFF = 10,
|
||||
};
|
||||
|
||||
enum adc_data_sel {
|
||||
ADC_DATA_SEL_NORM,
|
||||
ADC_DATA_SEL_LB, /* DAC loopback */
|
||||
ADC_DATA_SEL_RAMP, /* TBD */
|
||||
};
|
||||
|
||||
#define ADI_REG_CHAN_USR_CNTRL_1(c) (0x0420 + (c) * 0x40)
|
||||
#define ADI_USR_DATATYPE_BE (1 << 25)
|
||||
#define ADI_USR_DATATYPE_SIGNED (1 << 24)
|
||||
#define ADI_USR_DATATYPE_SHIFT(x) (((x) & 0xFF) << 16)
|
||||
#define ADI_TO_USR_DATATYPE_SHIFT(x) (((x) >> 16) & 0xFF)
|
||||
#define ADI_USR_DATATYPE_TOTAL_BITS(x) (((x) & 0xFF) << 8)
|
||||
#define ADI_TO_USR_DATATYPE_TOTAL_BITS(x) (((x) >> 8) & 0xFF)
|
||||
#define ADI_USR_DATATYPE_BITS(x) (((x) & 0xFF) << 0)
|
||||
#define ADI_TO_USR_DATATYPE_BITS(x) (((x) >> 0) & 0xFF)
|
||||
|
||||
#define ADI_REG_CHAN_USR_CNTRL_2(c) (0x0424 + (c) * 0x40)
|
||||
#define ADI_USR_DECIMATION_M(x) (((x) & 0xFFFF) << 16)
|
||||
#define ADI_TO_USR_DECIMATION_M(x) (((x) >> 16) & 0xFFFF)
|
||||
#define ADI_USR_DECIMATION_N(x) (((x) & 0xFFFF) << 0)
|
||||
#define ADI_TO_USR_DECIMATION_N(x) (((x) >> 0) & 0xFFFF)
|
||||
|
||||
#define ADI_REG_ADC_DP_DISABLE 0x00C0
|
||||
|
||||
/* PCORE Version > 8.00 */
|
||||
#define ADI_REG_DELAY(l) (0x0800 + (l) * 0x4)
|
||||
|
||||
/* debugfs direct register access */
|
||||
#define DEBUGFS_DRA_PCORE_REG_MAGIC 0x80000000
|
||||
|
||||
#define AXIADC_MAX_CHANNEL 16
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/clk/clkscale.h>
|
||||
|
||||
struct axiadc_chip_info {
|
||||
char *name;
|
||||
unsigned num_channels;
|
||||
unsigned num_shadow_slave_channels;
|
||||
const unsigned long *scan_masks;
|
||||
const int (*scale_table)[2];
|
||||
int num_scales;
|
||||
int max_testmode;
|
||||
unsigned long max_rate;
|
||||
struct iio_chan_spec channel[AXIADC_MAX_CHANNEL];
|
||||
};
|
||||
|
||||
struct axiadc_state {
|
||||
struct device *dev_spi;
|
||||
struct iio_info iio_info;
|
||||
struct clk *clk;
|
||||
struct gpio_desc *gpio_decimation;
|
||||
size_t regs_size;
|
||||
void __iomem *regs;
|
||||
void __iomem *slave_regs;
|
||||
unsigned max_usr_channel;
|
||||
unsigned adc_def_output_mode;
|
||||
unsigned max_count;
|
||||
unsigned id;
|
||||
unsigned pcore_version;
|
||||
unsigned decimation_factor;
|
||||
unsigned int oversampling_ratio;
|
||||
bool dp_disable;
|
||||
unsigned long long adc_clk;
|
||||
unsigned have_slave_channels;
|
||||
bool additional_channel;
|
||||
|
||||
struct iio_hw_consumer *frontend;
|
||||
|
||||
struct iio_chan_spec channels[AXIADC_MAX_CHANNEL];
|
||||
};
|
||||
|
||||
struct axiadc_converter {
|
||||
struct spi_device *spi;
|
||||
struct clk *clk;
|
||||
struct clock_scale adc_clkscale;
|
||||
struct clk *lane_clk;
|
||||
struct clk *sysref_clk;
|
||||
void *phy;
|
||||
struct gpio_desc *pwrdown_gpio;
|
||||
struct gpio_desc *reset_gpio;
|
||||
unsigned id;
|
||||
unsigned adc_output_mode;
|
||||
unsigned testmode[AXIADC_MAX_CHANNEL];
|
||||
unsigned scratch_reg[AXIADC_MAX_CHANNEL];
|
||||
unsigned long adc_clk;
|
||||
const struct axiadc_chip_info *chip_info;
|
||||
|
||||
struct delayed_work watchdog_work;
|
||||
bool sample_rate_read_only;
|
||||
|
||||
int (*reg_access)(struct iio_dev *indio_dev, unsigned int reg,
|
||||
unsigned int writeval, unsigned int *readval);
|
||||
int (*setup)(struct spi_device *spi, unsigned mode);
|
||||
|
||||
struct iio_chan_spec const *channels;
|
||||
int num_channels;
|
||||
const struct attribute_group *attrs;
|
||||
struct iio_dev *indio_dev;
|
||||
int (*read_raw)(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val,
|
||||
int *val2,
|
||||
long mask);
|
||||
|
||||
int (*write_raw)(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val,
|
||||
int val2,
|
||||
long mask);
|
||||
|
||||
int (*read_event_value)(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int *val,
|
||||
int *val2);
|
||||
|
||||
int (*write_event_value)(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int val,
|
||||
int val2);
|
||||
|
||||
int (*read_event_config)(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir);
|
||||
|
||||
int (*write_event_config)(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
int state);
|
||||
|
||||
int (*post_setup)(struct iio_dev *indio_dev);
|
||||
int (*post_iio_register)(struct iio_dev *indio_dev);
|
||||
int (*set_pnsel)(struct iio_dev *indio_dev, unsigned chan,
|
||||
enum adc_pn_sel sel);
|
||||
};
|
||||
|
||||
|
||||
|
||||
static inline struct axiadc_converter *to_converter(struct device *dev)
|
||||
{
|
||||
struct axiadc_converter *conv = spi_get_drvdata(to_spi_device(dev));
|
||||
|
||||
if (conv)
|
||||
return conv;
|
||||
|
||||
return ERR_PTR(-ENODEV);
|
||||
};
|
||||
|
||||
struct axiadc_spidev {
|
||||
struct device_node *of_nspi;
|
||||
struct device *dev_spi;
|
||||
};
|
||||
|
||||
/*
|
||||
* IO accessors
|
||||
*/
|
||||
|
||||
static inline void axiadc_write(struct axiadc_state *st, unsigned reg, unsigned val)
|
||||
{
|
||||
iowrite32(val, st->regs + reg);
|
||||
}
|
||||
|
||||
static inline unsigned int axiadc_read(struct axiadc_state *st, unsigned reg)
|
||||
{
|
||||
return ioread32(st->regs + reg);
|
||||
}
|
||||
|
||||
static inline void axiadc_slave_write(struct axiadc_state *st, unsigned reg, unsigned val)
|
||||
{
|
||||
iowrite32(val, st->slave_regs + reg);
|
||||
}
|
||||
|
||||
static inline unsigned int axiadc_slave_read(struct axiadc_state *st, unsigned reg)
|
||||
{
|
||||
return ioread32(st->slave_regs + reg);
|
||||
}
|
||||
|
||||
|
||||
static inline void axiadc_idelay_set(struct axiadc_state *st,
|
||||
unsigned lane, unsigned val)
|
||||
{
|
||||
if (ADI_AXI_PCORE_VER_MAJOR(st->pcore_version) > 8) {
|
||||
axiadc_write(st, ADI_REG_DELAY(lane), val);
|
||||
} else {
|
||||
axiadc_write(st, ADI_REG_DELAY_CNTRL, 0);
|
||||
axiadc_write(st, ADI_REG_DELAY_CNTRL,
|
||||
ADI_DELAY_ADDRESS(lane)
|
||||
| ADI_DELAY_WDATA(val)
|
||||
| ADI_DELAY_SEL);
|
||||
}
|
||||
}
|
||||
|
||||
int axiadc_set_pnsel(struct axiadc_state *st, int channel, enum adc_pn_sel sel);
|
||||
enum adc_pn_sel axiadc_get_pnsel(struct axiadc_state *st,
|
||||
int channel, const char **name);
|
||||
|
||||
int axiadc_configure_ring_stream(struct iio_dev *indio_dev,
|
||||
const char *dma_name);
|
||||
void axiadc_unconfigure_ring_stream(struct iio_dev *indio_dev);
|
||||
|
||||
#endif /* ADI_AXI_ADC_H_ */
|
@ -70,7 +70,7 @@ cd $OPENWIFI_DIR/driver/rx_intf
|
||||
make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE
|
||||
cd $OPENWIFI_DIR/driver/xpu
|
||||
make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE
|
||||
cd $OPENWIFI_DIR/driver/ad9361
|
||||
make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE
|
||||
# cd $OPENWIFI_DIR/driver/ad9361
|
||||
# make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE
|
||||
|
||||
cd $home_dir
|
||||
|
15
driver/sdr.c
15
driver/sdr.c
@ -45,11 +45,16 @@
|
||||
#include <linux/leds.h>
|
||||
|
||||
#define IIO_AD9361_USE_PRIVATE_H_
|
||||
#include "ad9361/ad9361_regs.h"
|
||||
#include "ad9361/ad9361.h"
|
||||
#include "ad9361/ad9361_private.h"
|
||||
#include <../../drivers/iio/adc/ad9361_regs.h>
|
||||
#include <../../drivers/iio/adc/ad9361.h>
|
||||
#include <../../drivers/iio/adc/ad9361_private.h>
|
||||
|
||||
#include <../../drivers/iio/frequency/cf_axi_dds.h>
|
||||
extern int ad9361_get_tx_atten(struct ad9361_rf_phy *phy, u32 tx_num);
|
||||
extern int ad9361_set_tx_atten(struct ad9361_rf_phy *phy, u32 atten_mdb,
|
||||
bool tx1, bool tx2, bool immed);
|
||||
extern int ad9361_ctrl_outs_setup(struct ad9361_rf_phy *phy,
|
||||
struct ctrl_outs_control *ctrl);
|
||||
|
||||
#include "../user_space/sdrctl_src/nl80211_testmode_def.h"
|
||||
#include "hw_def.h"
|
||||
@ -134,8 +139,8 @@ static void ad9361_rf_set_channel(struct ieee80211_hw *dev,
|
||||
|
||||
actual_tx_lo = conf->chandef.chan->center_freq - priv->tx_freq_offset_to_lo_MHz;
|
||||
|
||||
ad9361_clk_set_rate(priv->ad9361_phy->clks[RX_RFPLL], ( ((u64)1000000ull)*((u64)actual_rx_lo )>>1) );
|
||||
ad9361_clk_set_rate(priv->ad9361_phy->clks[TX_RFPLL], ( ((u64)1000000ull)*((u64)actual_tx_lo )>>1) );
|
||||
clk_set_rate(priv->ad9361_phy->clks[RX_RFPLL], ( ((u64)1000000ull)*((u64)actual_rx_lo )>>1) );
|
||||
clk_set_rate(priv->ad9361_phy->clks[TX_RFPLL], ( ((u64)1000000ull)*((u64)actual_tx_lo )>>1) );
|
||||
|
||||
if (actual_rx_lo<2412) {
|
||||
priv->rssi_correction = 153;
|
||||
|
@ -61,6 +61,8 @@ git checkout 2019_R1
|
||||
git pull origin 2019_R1
|
||||
# git reset --hard 4fea7c5
|
||||
cp $LINUX_KERNEL_CONFIG_FILE ./.config
|
||||
cp $OPENWIFI_DIR/driver/ad9361/ad9361.c $OPENWIFI_DIR/$LINUX_KERNEL_SRC_DIR_NAME/drivers/iio/adc/ad9361.c -rf
|
||||
|
||||
source $XILINX_DIR/SDK/2018.3/settings64.sh
|
||||
export ARCH=$ARCH_NAME
|
||||
export CROSS_COMPILE=$CROSS_COMPILE_NAME
|
||||
|
@ -141,11 +141,11 @@ sudo mkdir $SDCARD_DIR/rootfs/lib/modules
|
||||
|
||||
sudo mkdir $SDCARD_DIR/rootfs/lib/modules/$LINUX_KERNEL_SRC_DIR_NAME32
|
||||
sudo find $OPENWIFI_DIR/$LINUX_KERNEL_SRC_DIR_NAME32 -name \*.ko -exec cp {} $SDCARD_DIR/rootfs/lib/modules/$LINUX_KERNEL_SRC_DIR_NAME32/ \;
|
||||
sudo rm $SDCARD_DIR/rootfs/lib/modules/$LINUX_KERNEL_SRC_DIR_NAME32/{axidmatest.ko,adi_axi_hdmi.ko,ad9361_drv.ko} -f
|
||||
sudo rm $SDCARD_DIR/rootfs/lib/modules/$LINUX_KERNEL_SRC_DIR_NAME32/{axidmatest.ko,adi_axi_hdmi.ko} -f
|
||||
|
||||
sudo mkdir $SDCARD_DIR/rootfs/lib/modules/$LINUX_KERNEL_SRC_DIR_NAME64
|
||||
sudo find $OPENWIFI_DIR/$LINUX_KERNEL_SRC_DIR_NAME64 -name \*.ko -exec cp {} $SDCARD_DIR/rootfs/lib/modules/$LINUX_KERNEL_SRC_DIR_NAME64/ \;
|
||||
sudo rm $SDCARD_DIR/rootfs/lib/modules/$LINUX_KERNEL_SRC_DIR_NAME64/{axidmatest.ko,adi_axi_hdmi.ko,ad9361_drv.ko} -f
|
||||
sudo rm $SDCARD_DIR/rootfs/lib/modules/$LINUX_KERNEL_SRC_DIR_NAME64/{axidmatest.ko,adi_axi_hdmi.ko} -f
|
||||
|
||||
sudo rm $SDCARD_DIR/rootfs/etc/udev/rules.d/70-persistent-net.rules
|
||||
sudo cp $OPENWIFI_DIR/kernel_boot/70-persistent-net.rules $SDCARD_DIR/rootfs/etc/udev/rules.d/
|
||||
|
@ -66,24 +66,24 @@ then
|
||||
fi
|
||||
sleep 0.5
|
||||
|
||||
SUBMODULE=ad9361_drv
|
||||
if [ $last_input == "remote" ]
|
||||
then
|
||||
rm $SUBMODULE.ko
|
||||
sync
|
||||
wget ftp://192.168.10.1/driver/ad9361/$SUBMODULE.ko
|
||||
sync
|
||||
fi
|
||||
rmmod $SUBMODULE
|
||||
insmod $SUBMODULE.ko
|
||||
# SUBMODULE=ad9361_drv
|
||||
# if [ $last_input == "remote" ]
|
||||
# then
|
||||
# rm $SUBMODULE.ko
|
||||
# sync
|
||||
# wget ftp://192.168.10.1/driver/ad9361/$SUBMODULE.ko
|
||||
# sync
|
||||
# fi
|
||||
# rmmod $SUBMODULE
|
||||
# insmod $SUBMODULE.ko
|
||||
|
||||
echo check $SUBMODULE module is loaded or not
|
||||
checkModule $SUBMODULE
|
||||
if [ $? -eq 1 ]
|
||||
then
|
||||
return
|
||||
fi
|
||||
sleep 1
|
||||
# echo check $SUBMODULE module is loaded or not
|
||||
# checkModule $SUBMODULE
|
||||
# if [ $? -eq 1 ]
|
||||
# then
|
||||
# return
|
||||
# fi
|
||||
# sleep 1
|
||||
|
||||
echo "set RF frontend"
|
||||
# if [ $last_input == "remote" ]
|
||||
|
Loading…
Reference in New Issue
Block a user