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:
Xianjun Jiao 2021-05-05 16:44:39 +02:00
parent 23ba65e4fa
commit 56fcab2044
13 changed files with 47 additions and 4809 deletions

View File

@ -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
View 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.

View File

@ -1,9 +1,10 @@
/* /*
* AD9361 Agile RF Transceiver * AD9361 Agile RF Transceiver
* SPDX-FileCopyrightText: Copyright 2013-2015 Analog Devices Inc. *
* Modified by Xianjun jiao * Copyright 2013-2015 Analog Devices Inc.
* SPDX-License-Identifier: GPL-2.0-or-later *
*/ * Licensed under the GPL-2.
*/
//#define DEBUG //#define DEBUG
//#define _DEBUG //#define _DEBUG
#include <linux/module.h> #include <linux/module.h>
@ -1628,7 +1629,6 @@ static int ad9361_get_rx_gain(struct ad9361_rf_phy *phy,
out: out:
return rc; return rc;
} }
EXPORT_SYMBOL(ad9361_get_rx_gain);
static u8 ad9361_ensm_get_state(struct ad9361_rf_phy *phy) static u8 ad9361_ensm_get_state(struct ad9361_rf_phy *phy)
{ {
@ -2006,7 +2006,6 @@ out:
return rc; return rc;
} }
EXPORT_SYMBOL(ad9361_set_rx_gain);
static int ad9361_gc_update(struct ad9361_rf_phy *phy) 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: out:
return rc; 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; struct spi_device *spi = phy->spi;
u8 reg_val_buf[6]; u8 reg_val_buf[6];
@ -2205,7 +2203,6 @@ int ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi)
return rc; return rc;
} }
EXPORT_SYMBOL(ad9361_read_rssi);
static int ad9361_rx_adc_setup(struct ad9361_rf_phy *phy, unsigned long bbpll_freq, static int ad9361_rx_adc_setup(struct ad9361_rf_phy *phy, unsigned long bbpll_freq,
unsigned long adc_sampl_freq_Hz) 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 return ad9361_spi_write(spi, REG_CTRL_OUTPUT_ENABLE, ctrl->en_mask); // Ctrl Out [7:0] output enable
} }
EXPORT_SYMBOL(ad9361_ctrl_outs_setup); EXPORT_SYMBOL(ad9361_ctrl_outs_setup);
//************************************************************ //************************************************************
// Setup GPO // Setup GPO
//************************************************************ //************************************************************
@ -3780,7 +3776,7 @@ static int ad9361_gpo_setup(struct ad9361_rf_phy *phy, struct gpo_control *ctrl)
return 0; 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, struct rssi_control *ctrl,
bool is_update) bool is_update)
{ {
@ -3871,7 +3867,6 @@ int ad9361_rssi_setup(struct ad9361_rf_phy *phy,
return 0; return 0;
} }
EXPORT_SYMBOL(ad9361_rssi_setup);
static int ad9361_bb_clk_change_handler(struct ad9361_rf_phy *phy) 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; 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, static int ad9361_set_trx_clock_chain(struct ad9361_rf_phy *phy,
unsigned long *rx_path_clks, unsigned long *rx_path_clks,
unsigned long *tx_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; 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) u32 rf_rx_bw, u32 rf_tx_bw)
{ {
struct ad9361_rf_phy_state *st = phy->state; struct ad9361_rf_phy_state *st = phy->state;
@ -5257,7 +5246,6 @@ int ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy,
return 0; return 0;
} }
EXPORT_SYMBOL(ad9361_update_rf_bandwidth);
static int ad9361_verify_fir_filter_coef(struct ad9361_rf_phy *phy, static int ad9361_verify_fir_filter_coef(struct ad9361_rf_phy *phy,
enum fir_dest dest, enum fir_dest dest,

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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_ */

View File

@ -70,7 +70,7 @@ cd $OPENWIFI_DIR/driver/rx_intf
make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE
cd $OPENWIFI_DIR/driver/xpu cd $OPENWIFI_DIR/driver/xpu
make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE
cd $OPENWIFI_DIR/driver/ad9361 # cd $OPENWIFI_DIR/driver/ad9361
make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE # make KDIR=$LINUX_KERNEL_SRC_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE
cd $home_dir cd $home_dir

View File

@ -45,11 +45,16 @@
#include <linux/leds.h> #include <linux/leds.h>
#define IIO_AD9361_USE_PRIVATE_H_ #define IIO_AD9361_USE_PRIVATE_H_
#include "ad9361/ad9361_regs.h" #include <../../drivers/iio/adc/ad9361_regs.h>
#include "ad9361/ad9361.h" #include <../../drivers/iio/adc/ad9361.h>
#include "ad9361/ad9361_private.h" #include <../../drivers/iio/adc/ad9361_private.h>
#include <../../drivers/iio/frequency/cf_axi_dds.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 "../user_space/sdrctl_src/nl80211_testmode_def.h"
#include "hw_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; 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) ); 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[TX_RFPLL], ( ((u64)1000000ull)*((u64)actual_tx_lo )>>1) );
if (actual_rx_lo<2412) { if (actual_rx_lo<2412) {
priv->rssi_correction = 153; priv->rssi_correction = 153;

View File

@ -61,6 +61,8 @@ git checkout 2019_R1
git pull origin 2019_R1 git pull origin 2019_R1
# git reset --hard 4fea7c5 # git reset --hard 4fea7c5
cp $LINUX_KERNEL_CONFIG_FILE ./.config 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 source $XILINX_DIR/SDK/2018.3/settings64.sh
export ARCH=$ARCH_NAME export ARCH=$ARCH_NAME
export CROSS_COMPILE=$CROSS_COMPILE_NAME export CROSS_COMPILE=$CROSS_COMPILE_NAME

View File

@ -141,11 +141,11 @@ sudo mkdir $SDCARD_DIR/rootfs/lib/modules
sudo mkdir $SDCARD_DIR/rootfs/lib/modules/$LINUX_KERNEL_SRC_DIR_NAME32 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 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 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 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 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/ sudo cp $OPENWIFI_DIR/kernel_boot/70-persistent-net.rules $SDCARD_DIR/rootfs/etc/udev/rules.d/

View File

@ -66,24 +66,24 @@ then
fi fi
sleep 0.5 sleep 0.5
SUBMODULE=ad9361_drv # SUBMODULE=ad9361_drv
if [ $last_input == "remote" ] # if [ $last_input == "remote" ]
then # then
rm $SUBMODULE.ko # rm $SUBMODULE.ko
sync # sync
wget ftp://192.168.10.1/driver/ad9361/$SUBMODULE.ko # wget ftp://192.168.10.1/driver/ad9361/$SUBMODULE.ko
sync # sync
fi # fi
rmmod $SUBMODULE # rmmod $SUBMODULE
insmod $SUBMODULE.ko # insmod $SUBMODULE.ko
echo check $SUBMODULE module is loaded or not # echo check $SUBMODULE module is loaded or not
checkModule $SUBMODULE # checkModule $SUBMODULE
if [ $? -eq 1 ] # if [ $? -eq 1 ]
then # then
return # return
fi # fi
sleep 1 # sleep 1
echo "set RF frontend" echo "set RF frontend"
# if [ $last_input == "remote" ] # if [ $last_input == "remote" ]