blob: bf936b963a265478faa80acd6d43a48ed93658db [file] [log] [blame]
/*
* This file is part of the UWB stack for linux.
*
* Copyright (c) 2020-2021 Qorvo US, Inc.
*
* This software is provided under the GNU General Public License, version 2
* (GPLv2), as well as under a Qorvo commercial license.
*
* You may choose to use this software under the terms of the GPLv2 License,
* version 2 ("GPLv2"), as published by the Free Software Foundation.
* You should have received a copy of the GPLv2 along with this program. If
* not, see <http://www.gnu.org/licenses/>.
*
* This program is distributed under the GPLv2 in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GPLv2 for more
* details.
*
* If you cannot meet the requirements of the GPLv2, you may not use this
* software for any purpose without first obtaining a commercial license from
* Qorvo. Please contact Qorvo to inquire about licensing terms.
*/
#ifndef __DW3000_CORE_H
#define __DW3000_CORE_H
#include "dw3000.h"
/* Maximum SPI bus speed when PLL is not yet locked */
#define DW3000_SPI_SLOW_HZ 3000000
#define DW3000_GPIO_COUNT 9 /* GPIO0 to GPIO8 */
/* DW3000 wake-up latency. At least 2ms is required. */
#define DW3000_WAKEUP_LATENCY_US 15000
/* Define DW3000 PDOA modes */
#define DW3000_PDOA_M0 0x0 /* PDOA mode is off */
#define DW3000_PDOA_M1 0x1 /* PDOA mode 1 */
#define DW3000_PDOA_M2 0x2 /* PDOA mode 2 (reserved or not supported) */
#define DW3000_PDOA_M3 0x3 /* PDOA mode 3 */
#define DW3000_PDOA_CONFIG_MASK 0x3
/* Define DW3000 STS modes */
#define DW3000_STS_MODE_OFF 0x0 /* STS is off */
#define DW3000_STS_MODE_1 0x1 /* STS mode 1 */
#define DW3000_STS_MODE_2 0x2 /* STS mode 2 */
#define DW3000_STS_MODE_ND 0x3 /* STS with no data */
#define DW3000_STS_BASIC_MODES_MASK 0x3 /* STS basic modes */
#define DW3000_STS_MODE_SDC 0x8 /* Enable Super Deterministic Codes */
#define DW3000_STS_CONFIG_MASK 0xB
/* Offset of each area in CIR accumulator memory */
#define DW3000_ACC_MEM_IPATOV_OFFSET 0x0 /* Base address */
#define DW3000_ACC_MEM_PRF64_SIZE 1016 /* Bank size when PRF=64 MHz */
#define DW3000_ACC_MEM_PRF16_SIZE 992 /* Bank size when PRF=16 MHz */
#define DW3000_ACC_MEM_STS_OFFSET \
1024 /* Base address when STS enabled and pdoa != 3 */
#define DW3000_ACC_MEM_STS_SIZE \
512 /* Bank size when STS enabled and pdoa != 3 */
#define DW3000_ACC_MEM_STS_PDOA3_OFFSET \
(DW3000_ACC_MEM_STS_OFFSET + \
DW3000_ACC_MEM_STS_SIZE) /* Base address when sts enabled and pdoa mode 3 */
#define DW3000_ACC_MEM_STS_PDOA3_SZ \
512 /* Bank size when sts enabled and pdoa mode 3 */
/**
* DW3000_GET_STS_LEN_UNIT_VALUE() - Convert STS length enum into unit value
* @x: value from enum dw3000_sts_lengths
*
* Return: the STS length in unit of 8-symbols block.
*/
#define DW3000_GET_STS_LEN_UNIT_VALUE(x) ((u16)(1 << (x)))
/* Constants for specifying TX Preamble length in symbols */
#define DW3000_PLEN_4096 0x03 /* Standard preamble length 4096 symbols */
#define DW3000_PLEN_2048 0x0A /* Non-standard preamble length 2048 symbols */
#define DW3000_PLEN_1536 0x06 /* Non-standard preamble length 1536 symbols */
#define DW3000_PLEN_1024 0x02 /* Standard preamble length 1024 symbols */
#define DW3000_PLEN_512 0x0d /* Non-standard preamble length 512 symbols */
#define DW3000_PLEN_256 0x09 /* Non-standard preamble length 256 symbols */
#define DW3000_PLEN_128 0x05 /* Non-standard preamble length 128 symbols */
#define DW3000_PLEN_72 0x07 /* Non-standard length 72 */
#define DW3000_PLEN_32 0x04 /* Non-standard length 32 */
#define DW3000_PLEN_64 0x01 /* Standard preamble length 64 symbols */
/* Constants for specifying the (Nominal) mean Pulse Repetition Frequency
These are defined for direct write (with a shift if necessary) to CHAN_CTRL
and TX_FCTRL regs */
#define DW3000_PRF_16M 1 /* UWB PRF 16 MHz */
#define DW3000_PRF_64M 2 /* UWB PRF 64 MHz */
#define DW3000_PRF_SCP 3 /* SCP UWB PRF ~100 MHz */
/* Constants for specifying Start of Frame Delimiter (SFD) type */
#define DW3000_SFD_TYPE_STD 0 /* Standard short IEEE802154 SFD (8 symbols) */
#define DW3000_SFD_TYPE_DW_8 1 /* Decawave-defined 8 symbols SFD */
#define DW3000_SFD_TYPE_DW_16 2 /* Decawave-defined 16 symbols SFD */
#define DW3000_SFD_TYPE_4Z 3 /* IEEE802154z SFD (8 symbols) */
/* Constants for selecting the bit rate for data TX (and RX)
These are defined for write (with just a shift) the TX_FCTRL register */
#define DW3000_BR_850K 0 /* UWB bit rate 850 kbits/s */
#define DW3000_BR_6M8 1 /* UWB bit rate 6.8 Mbits/s */
/* Constants for selecting the PHR mode */
#define DW3000_PHRMODE_STD 0x0 /* standard PHR mode */
#define DW3000_PHRMODE_EXT 0x1 /* DW proprietary extended frames PHR mode */
/* Constants for selecting the bit rate for the PHR */
#define DW3000_PHRRATE_STD 0x0 /* standard PHR rate, 850 kbits/s */
#define DW3000_PHRRATE_DTA 0x1 /* PHR at data rate 6.8 Mbits/s */
/* Constants for specifying Preamble Acquisition Chunk (PAC) Size in symbols */
#define DW3000_PAC8 0 /* recommended for RX of preamble length 128 and below */
#define DW3000_PAC16 1 /* recommended for RX of preamble length 256 */
#define DW3000_PAC32 2 /* recommended for RX of preamble length 512 */
#define DW3000_PAC4 3 /* recommended for RX of preamble length < 127 */
enum spi_modes {
DW3000_SPI_RD_BIT = 0x0000U,
DW3000_SPI_WR_BIT = 0x8000U,
DW3000_SPI_AND_OR_8 = 0x8001U,
DW3000_SPI_AND_OR_16 = 0x8002U,
DW3000_SPI_AND_OR_32 = 0x8003U,
DW3000_SPI_AND_OR_MSK = 0x0003U,
};
/* Frame filtering configuration options */
#define DW3000_FF_ENABLE_802_15_4 0x2 /* use 802.15.4 filtering rules */
#define DW3000_FF_DISABLE 0x0 /* disable FF */
#define DW3000_FF_BEACON_EN 0x001 /* beacon frames allowed */
#define DW3000_FF_DATA_EN 0x002 /* data frames allowed */
#define DW3000_FF_ACK_EN 0x004 /* ack frames allowed */
#define DW3000_FF_MAC_EN 0x008 /* mac control frames allowed */
#define DW3000_FF_RSVD_EN 0x010 /* reserved frame types allowed */
#define DW3000_FF_MULTI_EN 0x020 /* multipurpose frames allowed */
#define DW3000_FF_FRAG_EN 0x040 /* fragmented frame types allowed */
#define DW3000_FF_EXTEND_EN 0x080 /* extended frame types allowed */
#define DW3000_FF_COORD_EN \
0x100 /* behave as coordinator (can receive frames
with no dest address (need PAN ID match)) */
#define DW3000_FF_IMPBRCAST_EN 0x200 /* allow MAC implicit broadcast */
/* DW3000 soft reset options */
#define DW3000_RESET_ALL 0x00
#define DW3000_RESET_CTRX 0x0f
#define DW3000_RESET_RX 0xef
#define DW3000_RESET_CLEAR 0xff
/* SYS_STATE_LO register information */
/* TSE is in IDLE (IDLE_PLL) */
#define DW3000_SYS_STATE_IDLE 0x3
/* TSE is in TX but TX is in IDLE */
#define DW3000_SYS_STATE_TXERR 0xD0000
/* Fast commands */
/* Turn off TX or RX, clear any TX/RX events and put DW3000 into IDLE */
#define DW3000_CMD_TXRXOFF 0x0
/* Start TX */
#define DW3000_CMD_TX 0x1
/* Enable RX */
#define DW3000_CMD_RX 0x2
/* Start delayed TX (RMARKER will be @ time set in DX_TIME register) */
#define DW3000_CMD_DTX 0x3
/* Enable RX @ time specified in DX_TIME register */
#define DW3000_CMD_DRX 0x4
/* Start delayed TX (RMARKER will be @ time = TX_TIME + DX_TIME) */
#define DW3000_CMD_DTX_TS 0x5
/* Enable RX @ time = TX_TIME + DX_TIME */
#define DW3000_CMD_DRX_TS 0x6
/* Start delayed TX (RMARKER will be @ time = RX_TIME + DX_TIME) */
#define DW3000_CMD_DTX_RS 0x7
/* Enable RX @ time = RX_TIME + DX_TIME */
#define DW3000_CMD_DRX_RS 0x8
/* Start delayed TX (RMARKER will be @ time = DREF_TIME + DX_TIME) */
#define DW3000_CMD_DTX_REF 0x9
/* Enable RX @ time = DREF_TIME + DX_TIME */
#define DW3000_CMD_DRX_REF 0xa
/* Start delayed TX (as DTX below), enable RX when TX done */
#define DW3000_CMD_DTX_W4R 0xd
/* Start TX (as below), enable RX when TX done */
#define DW3000_CMD_TX_W4R 0xc
/* Toggle double buffer pointer */
#define DW3000_CMD_DB_TOGGLE 0x13
/* Write to the Semaphore and try to reserve access (if it hasn't already been
reserved by the other master) */
#define DW3000_CMD_SEMA_REQ 0x14
/* Release the semaphore if it is currently reserved by this master. */
#define DW3000_CMD_SEMA_REL 0x15
/* Only SPI 2 can issue this command. Force access regardless of current
semaphore value. */
#define DW3000_CMD_SEMA_FORCE 0x16
/* Global digital reset including of the semaphore */
#define DW3000_CMD_SEMA_RESET 0x18
/* Global digital reset without reset of the semaphore */
#define DW3000_CMD_SEMA_RESET_NO_SEM 0x19
/* Enters sleep/deep sleep according to ANA_CFG - DEEPSLEEP_EN */
#define DW3000_CMD_ENTER_SLEEP 0x1A
/* Size of RX LUT configuration tables */
#define DW3000_CONFIGMRXLUT_MAX 7
#define DW3000_DGC_CFG 0x38
#define DW3000_DGC_CFG0 0x00000240
#define DW3000_DGC_CFG1 0x1a491248
#define DW3000_DGC_CFG2 0x2db248db
/* DW3000 SLEEP and WAKEUP configuration parameters */
#define DW3000_PGFCAL 0x0800
#define DW3000_GOTORX 0x0200
#define DW3000_GOTOIDLE 0x0100
#define DW3000_SEL_GEAR3 0x00C0
#define DW3000_SEL_GEAR2 0x0080 /* Short gear table */
#define DW3000_SEL_GEAR1 0x0040 /* SCP */
#define DW3000_SEL_GEAR0 0x0000 /* Long gear table */
#define DW3000_ALT_GEAR 0x0020
#define DW3000_LOADLDO 0x0010
#define DW3000_LOADDGC 0x0008
#define DW3000_LOADBIAS 0x0004
#define DW3000_RUNSAR 0x0002
/* OTP addresses definitions */
#define DW3000_LDOTUNELO_ADDRESS (0x04)
#define DW3000_LDOTUNEHI_ADDRESS (0x05)
#define DW3000_PARTID_ADDRESS (0x06)
#define DW3000_LOTID_ADDRESS (0x07)
#define DW3000_VBAT_ADDRESS (0x08)
#define DW3000_VTEMP_ADDRESS (0x09)
#define DW3000_XTRIM_ADDRESS (0x1E)
#define DW3000_OTPREV_ADDRESS (0x1F)
#define DW3000_BIAS_TUNE_ADDRESS (0xA)
#define DW3000_DGC_TUNE_ADDRESS (0x20)
#define DW3000_PLL_CC_ADDRESS (0x35)
/* Bit fields to select information to retrieve from OTP memory */
#define DW3000_READ_OTP_PID 0x10 /* read part ID from OTP */
#define DW3000_READ_OTP_LID 0x20 /* read lot ID from OTP */
#define DW3000_READ_OTP_BAT 0x40 /* read ref voltage from OTP */
#define DW3000_READ_OTP_TMP 0x80 /* read ref temperature from OTP */
/* The mean XTAL TRIM value measured on multiple E0 samples.
* During the initialization the XTAL TRIM value can be read from the OTP and
* in case it is not present, the default would be used instead. */
#define DW3000_DEFAULT_XTAL_TRIM 0x1f
/* The XTAL TRIM BIAS value for +/- 5PPM offset */
#define DW3000_XTAL_BIAS 0
/* Clock offset value under which the PDoA value is assumed bad. */
#define DW3000_CFO_THRESHOLD ((s16)(4 * (1 << 26) / 1000000))
/* All RX errors mask */
#define DW3000_SYS_STATUS_ALL_RX_ERR \
(DW3000_SYS_STATUS_RXPHE_BIT_MASK | DW3000_SYS_STATUS_RXFCE_BIT_MASK | \
DW3000_SYS_STATUS_RXFSL_BIT_MASK | DW3000_SYS_STATUS_RXSTO_BIT_MASK | \
DW3000_SYS_STATUS_ARFE_BIT_MASK | DW3000_SYS_STATUS_CIAERR_BIT_MASK | \
DW3000_SYS_STATUS_CPERR_BIT_MASK | \
DW3000_SYS_STATUS_LCSSERR_BIT_MASK)
/* User defined RX timeouts (frame wait timeout and preamble detect timeout)
mask. */
#define DW3000_SYS_STATUS_ALL_RX_TO \
(DW3000_SYS_STATUS_RXFTO_BIT_MASK | DW3000_SYS_STATUS_RXPTO_BIT_MASK)
/* All RX events after a correct packet reception mask */
#define DW3000_SYS_STATUS_ALL_RX_GOOD \
(DW3000_SYS_STATUS_RXFR_BIT_MASK | DW3000_SYS_STATUS_RXFCG_BIT_MASK | \
DW3000_SYS_STATUS_RXPRD_BIT_MASK | \
DW3000_SYS_STATUS_RXSFDD_BIT_MASK | \
DW3000_SYS_STATUS_RXPHD_BIT_MASK | \
DW3000_SYS_STATUS_CIA_DONE_BIT_MASK)
/* All TX events mask */
#define DW3000_SYS_STATUS_ALL_TX \
(DW3000_SYS_STATUS_AAT_BIT_MASK | DW3000_SYS_STATUS_TXFRB_BIT_MASK | \
DW3000_SYS_STATUS_TXPRS_BIT_MASK | DW3000_SYS_STATUS_TXPHS_BIT_MASK | \
DW3000_SYS_STATUS_TXFRS_BIT_MASK)
void dw3000_init_config(struct dw3000 *dw);
int dw3000_init(struct dw3000 *dw, bool check_idlerc);
void dw3000_remove(struct dw3000 *dw);
int dw3000_transfers_init(struct dw3000 *dw);
void dw3000_transfers_free(struct dw3000 *dw);
void dw3000_spitests(struct dw3000 *dw);
bool dw3000_spitests_enabled(struct dw3000 *dw);
int dw3000_wait_idle_state(struct dw3000 *dw);
int dw3000_poweron(struct dw3000 *dw);
int dw3000_poweroff(struct dw3000 *dw);
int dw3000_hardreset(struct dw3000 *dw);
int dw3000_softreset(struct dw3000 *dw);
int dw3000_check_devid(struct dw3000 *dw);
void dw3000_setup_regulators(struct dw3000 *dw);
int dw3000_setup_reset_gpio(struct dw3000 *dw);
int dw3000_setup_irq(struct dw3000 *dw);
int dw3000_setup_wifi_coex(struct dw3000 *dw);
int dw3000_setup_thread_cpu(struct dw3000 *dw, int *dw3000_thread_cpu);
int dw3000_setup_qos_latency(struct dw3000 *dw);
int dw3000_setup_regulator_delay(struct dw3000 *dw);
void dw3000_spi_queue_start(struct dw3000 *dw);
int dw3000_spi_queue_flush(struct dw3000 *dw);
int dw3000_spi_queue_reset(struct dw3000 *dw, int rc);
int dw3000_reg_read_fast(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u16 length, void *buffer);
int dw3000_reg_read32(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u32 *val);
int dw3000_reg_read16(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u16 *val);
int dw3000_reg_read8(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u8 *val);
int dw3000_reg_write_fast(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u16 length, const void *buffer, enum spi_modes mode);
int dw3000_reg_write32(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u32 val);
int dw3000_reg_write16(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u16 val);
int dw3000_reg_write8(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u8 val);
int dw3000_reg_modify32(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u32 _and, u32 _or);
int dw3000_reg_modify16(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u16 _and, u16 _or);
int dw3000_reg_modify8(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset,
u8 _and, u8 _or);
int dw3000_write_fastcmd(struct dw3000 *dw, u8 cmd);
int dw3000_xfer(struct dw3000 *dw, u32 reg_fileid, u16 reg_offset, u16 length,
void *buffer, enum spi_modes mode);
#define dw3000_reg_or8(dw, addr, offset, or_val) \
dw3000_reg_modify8(dw, addr, offset, -1, or_val)
#define dw3000_reg_and8(dw, addr, offset, and_val) \
dw3000_reg_modify8(dw, addr, offset, and_val, 0)
#define dw3000_reg_or16(dw, addr, offset, or_val) \
dw3000_reg_modify16(dw, addr, offset, -1, or_val)
#define dw3000_reg_and16(dw, addr, offset, and_val) \
dw3000_reg_modify16(dw, addr, offset, and_val, 0)
#define dw3000_reg_or32(dw, addr, offset, or_val) \
dw3000_reg_modify32(dw, addr, offset, -1, or_val)
#define dw3000_reg_and32(dw, addr, offset, and_val) \
dw3000_reg_modify32(dw, addr, offset, and_val, 0)
#define sts_to_pdoa(s, pdoa_enabled) \
((s) && (pdoa_enabled) ? DW3000_PDOA_M1 : DW3000_PDOA_M0)
#define dw3000_get_chip_name(dw) (dw3000_chip_versions[dw->chip_idx].name)
int dw3000_enable(struct dw3000 *dw);
int dw3000_disable(struct dw3000 *dw);
int dw3000_configure_chan(struct dw3000 *dw);
int dw3000_configure_pcode(struct dw3000 *dw);
int dw3000_configure_sfd_type(struct dw3000 *dw);
int dw3000_configure_phr_rate(struct dw3000 *dw);
int dw3000_configure_preamble_length_and_datarate(struct dw3000 *dw,
bool update_sfd_toc_pac);
int dw3000_set_eui64(struct dw3000 *dw, __le64 val);
int dw3000_set_panid(struct dw3000 *dw, __le16 val);
int dw3000_set_shortaddr(struct dw3000 *dw, __le16 val);
int dw3000_set_pancoord(struct dw3000 *dw, bool active);
int dw3000_set_promiscuous(struct dw3000 *dw, bool on);
int dw3000_set_sts_pdoa(struct dw3000 *dw, u8 sts_mode, u8 pdoa_mode);
int dw3000_set_sts_length(struct dw3000 *dw, enum dw3000_sts_lengths len);
int dw3000_configure_sts_key(struct dw3000 *dw, const u8 *key);
int dw3000_configure_sts_iv(struct dw3000 *dw, const u8 *iv);
int dw3000_load_sts_iv(struct dw3000 *dw);
int dw3000_configure_sys_cfg(struct dw3000 *dw, struct dw3000_config *config);
int dw3000_configure_hw_addr_filt(struct dw3000 *dw, unsigned long changed);
int dw3000_enable_auto_fcs(struct dw3000 *dw, bool on);
int dw3000_clear_sys_status(struct dw3000 *dw, u32 clear_bits);
int dw3000_clear_dss_status(struct dw3000 *dw, u8 clear_bits);
int dw3000_clear_spi_collision_status(struct dw3000 *dw, u8 clear_bits);
int dw3000_read_rx_timestamp(struct dw3000 *dw, u64 *rx_ts);
int dw3000_read_rdb_status(struct dw3000 *dw, u8 *status);
int dw3000_read_sys_status(struct dw3000 *dw, u32 *status);
int dw3000_read_sys_time(struct dw3000 *dw, u32 *sys_time);
int dw3000_rx_store_rssi(struct dw3000 *dw, struct dw3000_rssi *rssi,
u8 pkt_sts);
int dw3000_rx_calc_rssi(struct dw3000 *dw, struct dw3000_rssi *rssi,
struct mcps802154_rx_frame_info *info, u8 pkt_sts);
int dw3000_rx_stats_inc(struct dw3000 *dw, const enum dw3000_stats_items item,
struct dw3000_rssi *rssi);
u32 dw3000_get_dtu_time(struct dw3000 *dw);
int dw3000_forcetrxoff(struct dw3000 *dw);
int dw3000_do_rx_enable(struct dw3000 *dw,
const struct mcps802154_rx_frame_config *config,
int frame_idx);
int dw3000_rx_enable(struct dw3000 *dw, bool rx_delayed, u32 date_dtu,
u32 timeout_pac);
int dw3000_rx_disable(struct dw3000 *dw);
bool dw3000_rx_busy(struct dw3000 *dw, bool busy);
int dw3000_rx_stats_enable(struct dw3000 *dw, bool on);
void dw3000_rx_stats_clear(struct dw3000 *dw);
int dw3000_enable_autoack(struct dw3000 *dw, bool force);
int dw3000_disable_autoack(struct dw3000 *dw, bool force);
struct mcps802154_tx_frame_config;
int dw3000_do_tx_frame(struct dw3000 *dw,
const struct mcps802154_tx_frame_config *config,
struct sk_buff *skb, int frame_idx);
int dw3000_tx_setcwtone(struct dw3000 *dw, bool on);
int dw3000_config_antenna_gpios(struct dw3000 *dw);
int dw3000_set_tx_antenna(struct dw3000 *dw, int ant_set_id);
int dw3000_set_rx_antennas(struct dw3000 *dw, int ant_set_id,
bool pdoa_enabled);
s16 dw3000_read_pdoa(struct dw3000 *dw);
s16 dw3000_pdoa_to_aoa_lut(struct dw3000 *dw, s16 pdoa_rad_q11);
int dw3000_read_sts_timestamp(struct dw3000 *dw, u64 *sts_ts);
int dw3000_read_sts_quality(struct dw3000 *dw, s16 *acc_qual);
int dw3000_read_clockoffset(struct dw3000 *dw, s16 *cfo);
int dw3000_prog_xtrim(struct dw3000 *dw);
int dw3000_set_gpio_mode(struct dw3000 *dw, u32 mask, u32 mode);
int dw3000_set_gpio_dir(struct dw3000 *dw, u16 mask, u16 dir);
int dw3000_set_gpio_out(struct dw3000 *dw, u16 reset, u16 set);
int dw3000_otp_read32(struct dw3000 *dw, u16 addr, u32 *val);
int dw3000_otp_write32(struct dw3000 *dw, u16 addr, u32 data);
int dw3000_read_otp(struct dw3000 *dw, int mode);
int dw3000_read_frame_cir_data(struct dw3000 *dw,
struct mcps802154_rx_frame_info *info,
u64 utime);
int dw3000_cir_data_alloc_count(struct dw3000 *dw, u16 nrecord);
void dw3000_sysfs_init(struct dw3000 *dw);
void dw3000_sysfs_remove(struct dw3000 *dw);
void dw3000_isr(struct dw3000 *dw);
enum hrtimer_restart dw3000_idle_timeout(struct hrtimer *timer);
int dw3000_idle_cancel_timer(struct dw3000 *dw);
void dw3000_wakeup_timer_start(struct dw3000 *dw, int delay_us);
void dw3000_wakeup_and_wait(struct dw3000 *dw);
int dw3000_deep_sleep_and_wakeup(struct dw3000 *dw, int delay_us);
int dw3000_idle(struct dw3000 *dw, bool timestamp, u32 timestamp_dtu,
dw3000_idle_timeout_cb idle_timeout_cb,
enum operational_state next_operational_state);
int dw3000_deepsleep_wakeup_now(struct dw3000 *dw,
dw3000_idle_timeout_cb idle_timeout_cb,
u32 timestamp_dtu,
enum operational_state next_operational_state);
int dw3000_can_deep_sleep(struct dw3000 *dw, int delay_us);
int dw3000_trace_rssi_info(struct dw3000 *dw, u32 regid, char *chipver);
int dw3000_testmode_continuous_tx_start(struct dw3000 *dw, u32 frame_length,
u32 rate);
int dw3000_testmode_continuous_tx_stop(struct dw3000 *dw);
int dw3000_nfcc_coex_prepare_config(struct dw3000 *dw);
int dw3000_nfcc_coex_restore_config(struct dw3000 *dw);
/* Preamble length related information. */
struct dw3000_plen_info {
/* Preamble length in symbols. */
int symb;
/* PAC size in symbols. */
int pac_symb;
/* Register value for this preamble length. */
uint8_t dw_reg;
/* Register value for PAC size. */
uint8_t dw_pac_reg;
};
extern const struct dw3000_plen_info _plen_info[];
/* Chip per symbol information. */
extern const int _chip_per_symbol_info[];
/* PRF related information. */
struct dw3000_prf_info {
/* Number of chips per symbol. */
int chip_per_symb;
};
extern const struct dw3000_prf_info _prf_info[];
static inline int dw3000_get_sfd_symb(struct dw3000 *dw)
{
/*
* SFD_TYPE_STD, SFD_TYPE_DW_8, SFD_TYPE_4Z : 8 symbols
* SFD_TYPE_DW_16 : 16 symbols
*/
return dw->config.sfdType == DW3000_SFD_TYPE_DW_16 ? 16 : 8;
}
static inline int dw3000_compute_shr_dtu(struct dw3000 *dw)
{
const struct dw3000_plen_info *plen_info =
&_plen_info[dw->config.txPreambLength - 1];
const int chip_per_symb =
_prf_info[dw->config.txCode >= 9 ? DW3000_PRF_64M :
DW3000_PRF_16M]
.chip_per_symb;
const int shr_symb = plen_info->symb + dw3000_get_sfd_symb(dw);
return shr_symb * chip_per_symb / DW3000_CHIP_PER_DTU;
}
static inline int compute_shr_dtu_from_conf(
const struct mcps802154_hrp_uwb_params *hrp_uwb_params)
{
const int preamble_symb = hrp_uwb_params->psr;
const int chip_per_symb =
_prf_info[hrp_uwb_params->prf == MCPS802154_PRF_64 ?
DW3000_PRF_64M :
DW3000_PRF_16M]
.chip_per_symb;
/* The only possible sfd number of symbols is 8. */
const int sfd_symb = 8;
const int shr_symb = preamble_symb + sfd_symb;
return shr_symb * chip_per_symb / DW3000_CHIP_PER_DTU;
}
static inline int dw3000_compute_symbol_dtu(struct dw3000 *dw)
{
const int chip_per_symb =
_prf_info[dw->config.txCode >= 9 ? DW3000_PRF_64M :
DW3000_PRF_16M]
.chip_per_symb;
return chip_per_symb / DW3000_CHIP_PER_DTU;
}
static inline int dw3000_compute_chips_per_pac(struct dw3000 *dw)
{
const int pac_symb = _plen_info[dw->config.txPreambLength - 1].pac_symb;
const int chip_per_symb =
_prf_info[dw->config.txCode >= 9 ? DW3000_PRF_64M :
DW3000_PRF_16M]
.chip_per_symb;
return chip_per_symb * pac_symb;
}
static inline int dw3000_compute_pre_timeout_pac(struct dw3000 *dw)
{
/* Must be called AFTER dw->chips_per_pac initialisation */
const int symb = _plen_info[dw->config.txPreambLength - 1].symb;
const int pac_symb = _plen_info[dw->config.txPreambLength - 1].pac_symb;
return (DW3000_RX_ENABLE_STARTUP_DLY * DW3000_CHIP_PER_DLY +
dw->chips_per_pac - 1) /
dw->chips_per_pac +
symb / pac_symb + 2;
}
static inline int dw3000_frame_duration_dtu(struct dw3000 *dw,
int payload_bytes, bool with_shr)
{
const struct dw3000_prf_info *prf_info =
&_prf_info[dw->config.txCode >= 9 ? DW3000_PRF_64M :
DW3000_PRF_16M];
int chip_per_symbol_phr = _chip_per_symbol_info[dw->config.phrRate];
int chip_per_symbol_data = _chip_per_symbol_info[dw->config.dataRate];
/* STS part */
const u8 sts_mode = dw->config.stsMode & DW3000_STS_BASIC_MODES_MASK;
const int sts_symb =
sts_mode == DW3000_STS_MODE_OFF ? 0 : 8 << dw->config.stsLength;
const int sts_chips = sts_symb * prf_info->chip_per_symb;
/* PHR part. */
const int phr_tail_bits = sts_mode == DW3000_STS_MODE_ND ? 0 : 19 + 2;
const int phr_chips = phr_tail_bits /* 1 bit/symbol */
* chip_per_symbol_phr;
/* Data part, 48 Reed-Solomon bits per 330 bits. */
const int data_bits = sts_mode == DW3000_STS_MODE_ND ?
0 :
(payload_bytes + IEEE802154_FCS_LEN) * 8;
const int data_rs_bits = data_bits + (data_bits + 329) / 330 * 48;
const int data_chips = data_rs_bits /* 1 bit/symbol */
* chip_per_symbol_data;
/* Done, convert to dtu. */
return ((sts_chips + phr_chips + data_chips) / DW3000_CHIP_PER_DTU) +
(with_shr ? dw->llhw->shr_dtu : 0);
}
static inline void dw3000_update_timings(struct dw3000 *dw)
{
struct mcps802154_llhw *llhw = dw->llhw;
/* Update configuration dependent timings */
llhw->shr_dtu = dw3000_compute_shr_dtu(dw);
llhw->symbol_dtu = dw3000_compute_symbol_dtu(dw);
/* The CCA detection time shall be equivalent to 40 data symbol periods,
Tdsym, for a nominal 850 kb/s, or equivalently, at least 8 (multiplexed)
preamble symbols should be captured in the CCA detection time. */
llhw->cca_dtu = 8 * llhw->symbol_dtu;
dw->chips_per_pac = dw3000_compute_chips_per_pac(dw);
dw->pre_timeout_pac = dw3000_compute_pre_timeout_pac(dw);
}
/**
* dw3000_dtu_to_ktime() - compute absolute ktime for the specified DTU time
* @dw: the DW device
* @ts_dtu: timestamp in DTU unit to convert
*
* Formula:
* ktime = (ts_dtu - dtu0) * D / N + ktime0
* Where:
* N = DW3000_DTU_FREQ = 15600000
* D = 1000000000
*
* D/N = 1000000000/15600000 = 10000/156
* dtu0 always 0.
*
* Return: the computed kernel time in ns
*/
static inline s64 dw3000_dtu_to_ktime(struct dw3000 *dw, u32 ts_dtu)
{
return dw->time_zero_ns +
(10000ll * ts_dtu / (DW3000_DTU_FREQ / 100000));
}
/**
* dw3000_ktime_to_dtu() - compute current DTU time
* @dw: the DW device
* @timestamp_ns: kernel time in ns
*
* Formula:
* dtu = (ktime - ktime0) * N / D + dtu0
* Where:
* N = DW3000_DTU_FREQ = 15600000
* D = 1000000000
*
* N/D = 15600000/1000000000 = 156/10000
* dtu0 always 0.
*
* Return: driver DTU time
*/
static inline u32 dw3000_ktime_to_dtu(struct dw3000 *dw, s64 timestamp_ns)
{
timestamp_ns -= dw->time_zero_ns;
return (u32)(timestamp_ns * (DW3000_DTU_FREQ / 100000) / 10000);
}
/**
* dw3000_dtu_to_sys_time() - compute DW SYS_TIME from DTU time
* @dw: the DW device
* @dtu: the DTU timestamp to convert to SYS_TIME
*
* Return: the value to write to SYS_TIME register
*/
static inline u32 dw3000_dtu_to_sys_time(struct dw3000 *dw, u32 dtu)
{
const int N = DW3000_DTU_PER_SYS_POWER;
u32 dtu_sync = dw->dtu_sync;
u32 sys_time_sync = dw->sys_time_sync;
return ((dtu - dtu_sync) << N) + sys_time_sync;
}
/**
* dw3000_sys_time_to_dtu() - compute current DTU time from SYS_TIME
* @dw: the DW device
* @sys_time: the DW device SYS_TIME register value to convert to DTU
* @dtu_near: a DTU time which must be in the past relative to sys_time, at less
* than half the SYS_TIME rollover period
*
* Return: the corresponding DTU time
*/
static inline u32 dw3000_sys_time_to_dtu(struct dw3000 *dw, u32 sys_time,
u32 dtu_near)
{
const int N = DW3000_DTU_PER_SYS_POWER;
u32 dtu_sync = dw->dtu_sync;
u32 sys_time_sync = dw->sys_time_sync;
u32 dtu_lsb = (sys_time - (sys_time_sync - (dtu_sync << N))) >> N;
u32 dtu_add = ((~dtu_lsb & dtu_near) & (1 << (31 - N))) << 1;
u32 mask = (1 << (32 - N)) - 1;
return ((dtu_near & ~mask) | dtu_lsb) + dtu_add;
}
/**
* dw3000_sys_time_rctu_to_dtu() - compute current DTU time from RCTU.
* @dw: the DW device.
* @timestamp_rctu: The DW device RX_STAMP register value in RCTU to convert to DTU.
* The RCTU, Ranging Counter Time Unit, is approximately 15.65 picoseconds long.
*
* Return: The corresponding DTU time.
*/
static inline u32 dw3000_sys_time_rctu_to_dtu(struct dw3000 *dw,
u64 timestamp_rctu)
{
u32 sys_time = (u32)(timestamp_rctu / DW3000_RCTU_PER_SYS);
u32 dtu_near = dw3000_get_dtu_time(dw) - DW3000_DTU_FREQ;
return dw3000_sys_time_to_dtu(dw, sys_time, dtu_near);
}
/**
* dw3000_reset_rctu_conv_state() - reset RCTU converter
* @dw: the DW device
*
* Called during a stop, rx_disable, reset and idle.
*/
static inline void dw3000_reset_rctu_conv_state(struct dw3000 *dw)
{
dw->rctu_conv.state = UNALIGNED;
}
/**
* dw3000_resync_rctu_conv_state() - resync RCTU converter
* @dw: the DW device
*
* Called during a wake-up from deep sleep.
*/
static inline void dw3000_resync_rctu_conv_state(struct dw3000 *dw)
{
if (dw->rctu_conv.state == ALIGNED_SYNCED)
dw->rctu_conv.state = ALIGNED;
}
static inline int pac_to_dly(struct mcps802154_llhw *llhw, int pac)
{
struct dw3000 *dw = llhw->priv;
return (pac * dw->chips_per_pac / DW3000_CHIP_PER_DLY);
}
static inline int dtu_to_pac(struct mcps802154_llhw *llhw, int timeout_dtu)
{
struct dw3000 *dw = llhw->priv;
return (timeout_dtu * DW3000_CHIP_PER_DTU + dw->chips_per_pac - 1) /
dw->chips_per_pac;
}
static inline int dtu_to_dly(struct mcps802154_llhw *llhw, int dtu)
{
return (dtu * DW3000_CHIP_PER_DTU / DW3000_CHIP_PER_DLY);
}
#endif /* __DW3000_CORE_H */