blob: 4c449bc1e9229cd204e62f89032cbdb6ddc68992 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2020, The Linux foundation. All rights reserved.
*/
#ifndef __WIGIG_SENSING_H__
#define __WIGIG_SENSING_H__
#include <linux/cdev.h>
#include <linux/circ_buf.h>
#include <linux/kfifo.h>
#include <linux/ktime.h>
#include <linux/slab.h>
#include <uapi/misc/wigig_sensing_uapi.h>
#ifdef pr_fmt
#undef pr_fmt
#endif
#define pr_fmt(fmt) "[wigig_sensing]: " fmt
/* Registers */
#define RGF_USER_SPI_SPI_MBOX_FILL_STATUS (0x880080)
#define RGF_USER_SPI_SPI_EXT_MBOX_OUTB (0x880084)
#define RGF_USER_SPI_SPI_MBOX_INB (0x880088)
#define RGF_SPI_FIFO_CONTROL_ADDR (0x8800A0)
#define RGF_SPI_FIFO_WR_PTR_ADDR (0x88009C)
#define RGF_SPI_FIFO_RD_PTR_ADDR (0x880098)
#define RGF_SPI_FIFO_BASE_ADDR_ADDR (0x880094)
#define RGF_SPI_CONTROL_ADDR (0x880090)
#define RGF_SPI_CONFIG_ADDR (0x88008C)
#define SPIS_TRNS_LEN_REG_ADDR (0x50)
#define ADDR_WIDTH (3)
#define DUMMY_BYTES_WIDTH (4)
#define OPCODE_WIDTH (1)
#define SPIS_SANITY_REG_ADDR (0x0)
#define SPIS_SANITY_REG_VAL (0xDEADBEEF)
#define SPIS_CFG_REG_ADDR (0xC)
#define JTAG_ID_REG_ADDR (0x880000)
#define JTAG_ID (0x1007E0E1)
/* optimized configuration with 4 dummy bytes */
#define SPIS_CONFIG_REG_OPT_VAL (0x44200800)
#define SPIS_EXTENDED_RESET_COMMAND_LEN (225)
#define MAX_SPI_READ_CHUNKS (10)
#define SPI_MIN_TRANSACTION_SIZE (512)
#define SPI_MAX_TRANSACTION_SIZE (8*1024)
#define SPI_CMD_TRANSACTION_SIZE (512)
#define SPI_BUFFER_SIZE (SPI_MAX_TRANSACTION_SIZE + OPCODE_WIDTH + \
ADDR_WIDTH + DUMMY_BYTES_WIDTH)
#define SPI_CMD_BUFFER_SIZE (SPI_CMD_TRANSACTION_SIZE + OPCODE_WIDTH + \
ADDR_WIDTH + DUMMY_BYTES_WIDTH)
#define INT_FW_READY BIT(24)
#define INT_DATA_READY BIT(25)
#define INT_FIFO_READY BIT(26)
#define INT_DONT_DEASSERT BIT(27)
#define INT_SYSASSERT BIT(29)
#define INT_DEEP_SLEEP_EXIT BIT(30)
union user_rgf_spi_status {
struct {
u16 fill_level:16;
int reserved1:3;
u8 spi_fifo_thr_status:1;
u8 spi_fifo_empty_status:1;
u8 spi_fifo_full_status:1;
u8 spi_fifo_underrun_status:1;
u8 spi_fifo_overrun_status:1;
/* mbox_outb */
u8 int_fw_ready:1; /* FW MBOX ready */
u8 int_data_ready:1; /* data available on FIFO */
u8 int_fifo_ready:1; /* FIFO status update */
u8 int_dont_deassert:1; /* Don't deassert DRI */
u8 reserved3:1;
u8 int_sysassert:1; /* SYSASSERT occurred */
u8 int_deep_sleep_exit:1;
u8 reserved4:1;
} __packed b;
u32 v;
} __packed;
union user_rgf_spi_mbox_inb {
struct {
u8 mode:4;
u8 channel_request:4;
u32 reserved:23;
u8 deassert_dri:1;
} __packed b;
u32 v;
} __packed;
union rgf_spi_config {
struct {
u16 size:16;
u8 reserved1:8;
u8 mbox_auto_clear_disable:1;
u8 status_auto_clear_disable:1;
u8 reserved2:5;
u8 enable:1;
} __packed b;
u32 v;
} __packed;
union rgf_spi_control {
struct {
u8 read_ptr_clear:1;
u8 fill_level_clear:1;
u8 thresh_reach_clear:1;
u8 status_field_clear:1;
u8 mbox_field_clear:1;
u32 reserved:27;
} __packed b;
u32 v;
} __packed;
struct cir_data {
struct circ_buf b;
u32 size_bytes;
struct mutex lock;
};
struct spi_fifo {
u32 wr_ptr;
u32 rd_ptr;
u32 base_addr;
union rgf_spi_config config;
union rgf_spi_control control;
};
/**
* State machine states
* TODO: Document states
*/
enum wigig_sensing_stm_e {
WIGIG_SENSING_STATE_MIN = 0,
WIGIG_SENSING_STATE_INITIALIZED,
WIGIG_SENSING_STATE_READY_STOPPED,
WIGIG_SENSING_STATE_SEARCH,
WIGIG_SENSING_STATE_FACIAL,
WIGIG_SENSING_STATE_GESTURE,
WIGIG_SENSING_STATE_CUSTOM,
WIGIG_SENSING_STATE_GET_PARAMS,
WIGIG_SENSING_STATE_SYS_ASSERT,
WIGIG_SENSING_STATE_MAX,
};
struct wigig_sensing_stm {
bool auto_recovery;
bool fw_is_ready;
bool spi_malfunction;
bool spi_ready;
bool waiting_for_deep_sleep_exit;
bool waiting_for_deep_sleep_exit_first_pass;
bool burst_size_ready;
bool change_mode_in_progress;
enum wigig_sensing_stm_e state;
enum wigig_sensing_mode mode;
u32 burst_size;
u32 channel;
u32 channel_request;
enum wigig_sensing_stm_e state_request;
enum wigig_sensing_mode mode_request;
};
enum spi_stats_meas {
SPI_STATS_MEAS_MIN,
SPI_STATS_MEAS_SANITY = SPI_STATS_MEAS_MIN,
SPI_STATS_MEAS_DEASSERT,
SPI_STATS_MEAS_DRI_PROC,
SPI_STATS_MEAS_MBOX_FILL_STATUS,
SPI_STATS_MEAS_CHANGE_MODE,
SPI_STATS_MEAS_DATA_READY,
SPI_STATS_MEAS_MAX,
};
#define SPI_STATS_MAX_NAME_LEN (20)
struct spi_stats {
char name[SPI_STATS_MAX_NAME_LEN];
atomic64_t min;
atomic64_t max;
atomic64_t acc;
atomic_t num_meas;
ktime_t start, delta;
};
struct wigig_sensing_ctx {
dev_t wigig_sensing_dev;
struct cdev cdev;
struct class *class;
struct device *dev;
struct spi_device *spi_dev;
struct dentry *debugfs_dent;
/* Locks */
struct mutex ioctl_lock;
struct mutex file_lock;
struct mutex spi_lock;
struct mutex dri_lock;
wait_queue_head_t cmd_wait_q;
wait_queue_head_t data_wait_q;
/* DRI */
struct gpio_desc *dri_gpio;
int dri_irq;
bool opened;
/* Memory buffers for SPI transactions */
u8 *tx_buf;
u8 *rx_buf;
u8 *cmd_buf;
u8 *cmd_reply_buf;
/* SPI FIFO parameters */
struct spi_fifo spi_fifo;
struct wigig_sensing_stm stm;
u32 last_read_length;
union user_rgf_spi_mbox_inb inb_cmd;
u32 spi_transaction_size;
/* CIR buffer */
struct cir_data cir_data;
u8 *temp_buffer;
bool event_pending;
DECLARE_KFIFO(events_fifo, enum wigig_sensing_event, 8);
u32 dropped_bursts;
/* Statistics */
struct spi_stats spi_stats[SPI_STATS_MEAS_MAX];
};
#endif /* __WIGIG_SENSING_H__ */