Files
2025-08-12 22:16:57 +02:00

330 lines
9.6 KiB
C
Executable File

/******************************************************************************
* Copyright (C) 2015, The Linux Foundation. All rights reserved.
* Copyright (C) 2019-2022 NXP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
******************************************************************************/
#ifndef _COMMON_H_
#define _COMMON_H_
#include <linux/cdev.h>
#include <linux/fs.h>
#if IS_ENABLED(CONFIG_SAMSUNG_NFC)
#include <linux/clk.h>
#include <linux/reboot.h>
#include "nfc_wakelock.h"
#ifdef CONFIG_SEC_NFC_LOGGER
#ifdef CONFIG_NFC_NXP_COMBINED
#include "../nfc_logger/nfc_logger.h"
#else
#include "nfc_logger/nfc_logger.h"
#endif
#endif
#endif
#include "i2c_drv.h"
/* Max device count for this driver */
#define DEV_COUNT 1
/* i2c device class */
#if IS_ENABLED(CONFIG_SAMSUNG_NFC)
#define CLASS_NAME "nfc_sec"
#else
#define CLASS_NAME "nfc"
#endif
/* NFC character device name, this will be in /dev/ */
#define NFC_CHAR_DEV_NAME "pn547"
/* NCI packet details */
#define NCI_CMD (0x20)
#define NCI_RSP (0x40)
#define NCI_HDR_LEN (3)
#define NCI_HDR_IDX (0)
#define NCI_HDR_OID_IDX (1)
#define NCI_PAYLOAD_IDX (3)
#define NCI_PAYLOAD_LEN_IDX (2)
/* FW DNLD packet details */
#define DL_HDR_LEN (2)
#define DL_CRC_LEN (2)
#define MAX_NCI_PAYLOAD_LEN (255)
#define MAX_NCI_BUFFER_SIZE (NCI_HDR_LEN + MAX_NCI_PAYLOAD_LEN)
/*
* Compile time option to select maximum writer buffer of either 4K or 550 bytes.
* Default value is set as 4K. This value shall be chosen based on Hal flag "HDLL_4K_WRITE_SUPPORTED".
* undef or comment HDLL_4K_WRITE_SUPPORTED to fallback to 550 bytes write frame buffer.
*/
#define HDLL_4K_WRITE_SUPPORTED
#ifdef HDLL_4K_WRITE_SUPPORTED
#define MAX_DL_PAYLOAD_LEN (4096)
#else
#define MAX_DL_PAYLOAD_LEN (550)
#endif
#define MAX_DL_BUFFER_SIZE (DL_HDR_LEN + DL_CRC_LEN + \
MAX_DL_PAYLOAD_LEN)
/* Retry count for normal write */
#define NO_RETRY (1)
/* Maximum retry count for standby writes */
#define MAX_RETRY_COUNT (3)
#define MAX_WRITE_IRQ_COUNT (5)
#define MAX_IRQ_WAIT_TIME (90)
#define WAKEUP_SRC_TIMEOUT (2000)
/* command response timeout */
#define NCI_CMD_RSP_TIMEOUT_MS (2000)
/* Time to wait for NFCC to be ready again after any change in the GPIO */
#define NFC_GPIO_SET_WAIT_TIME_US (15000)
/* Time to wait before retrying writes */
#define WRITE_RETRY_WAIT_TIME_US (3000)
/* Time to wait before retrying read for some specific usecases */
#define READ_RETRY_WAIT_TIME_US (3500)
#define NFC_MAGIC (0xE9)
/* Ioctls */
/* The type should be aligned with MW HAL definitions */
#define NFC_SET_PWR _IOW(NFC_MAGIC, 0x01, uint64_t)
#define ESE_SET_PWR _IOW(NFC_MAGIC, 0x02, uint64_t)
#define ESE_GET_PWR _IOR(NFC_MAGIC, 0x03, uint64_t)
#define NFC_GET_GPIO_STATUS _IOR(NFC_MAGIC, 0x05, uint64_t)
#if IS_ENABLED(CONFIG_SAMSUNG_NFC)
#define CONFIG_SAMSUNG_NFC_DEBUG
#define FEATURE_CORE_RESET_NTF_CHECK
#define DTS_IRQ_GPIO_STR "pn547,irq-gpio"
#define DTS_VEN_GPIO_STR "pn547,ven-gpio"
#define DTS_FWDN_GPIO_STR "pn547,firm-gpio"
enum ap_vendors {
AP_VENDOR_NONE,
AP_VENDOR_SLSI,
AP_VENDOR_QCT,
AP_VENDOR_MTK,
AP_VENDOR_ERR
};
enum lpm_status {
LPM_NO_SUPPORT = -1,
LPM_FALSE,
LPM_TRUE
};
#else
#define DTS_IRQ_GPIO_STR "nxp,sn-irq"
#define DTS_VEN_GPIO_STR "nxp,sn-ven-rstn"
#define DTS_FWDN_GPIO_STR "nxp,sn-dwl-req"
#endif
/* Each GPIO occupies consecutive two bits */
#define GPIO_POS_SHIFT_VAL 2
/* Two bits to indicate GPIO status (Invalid(-2), Set(1) or Reset(0)) */
#define GPIO_STATUS_MASK_BITS 3
#ifndef CONFIG_SEC_NFC_LOGGER
#define NFC_LOG_ERR(fmt, ...) pr_err("sec_nfc: "fmt, ##__VA_ARGS__)
#define NFC_LOG_INFO(fmt, ...) pr_info("sec_nfc: "fmt, ##__VA_ARGS__)
#define NFC_LOG_INFO_WITH_DATE(fmt, ...) pr_info("sec_nfc: "fmt, ##__VA_ARGS__)
#define NFC_LOG_DBG(fmt, ...) pr_debug("sec_nfc: "fmt, ##__VA_ARGS__)
#define NFC_LOG_REC(fmt, ...) do { } while (0)
#define nfc_print_hex_dump(a, b, c) do { } while (0)
#define nfc_logger_init() do { } while (0)
#define nfc_logger_deinit() do { } while (0)
#define nfc_logger_set_max_count(a) do { } while (0)
#define nfc_logger_register_nfc_stauts_func(a) do { } while (0)
#endif /* CONFIG_SEC_NFC_LOGGER */
enum nfcc_ioctl_request {
/* NFC disable request with VEN LOW */
NFC_POWER_OFF = 0,
/* NFC enable request with VEN Toggle */
NFC_POWER_ON,
/* firmware download request with VEN Toggle */
NFC_FW_DWL_VEN_TOGGLE,
/* ISO reset request */
NFC_ISO_RESET,
/* request for firmware download gpio HIGH */
NFC_FW_DWL_HIGH,
/* VEN hard reset request */
NFC_VEN_FORCED_HARD_RESET,
/* request for firmware download gpio LOW */
NFC_FW_DWL_LOW,
};
/* nfc platform interface type */
enum interface_flags {
/* I2C physical IF for NFCC */
PLATFORM_IF_I2C = 0,
};
/* nfc state flags */
enum nfc_state_flags {
/* nfc in unknown state */
NFC_STATE_UNKNOWN = 0,
/* nfc in download mode */
NFC_STATE_FW_DWL = 0x1,
/* nfc booted in NCI mode */
NFC_STATE_NCI = 0x2,
/* nfc booted in Fw teared mode */
NFC_STATE_FW_TEARED = 0x4,
};
/*
* Power state for IBI handing, mainly needed to defer the IBI handling
* for the IBI received in suspend state to do it later in resume call
*/
enum pm_state_flags {
PM_STATE_NORMAL = 0,
PM_STATE_SUSPEND,
PM_STATE_IBI_BEFORE_RESUME,
};
/* Enum for GPIO values */
enum gpio_values {
GPIO_INPUT = 0x0,
GPIO_OUTPUT = 0x1,
GPIO_HIGH = 0x2,
GPIO_OUTPUT_HIGH = 0x3,
GPIO_IRQ = 0x4,
};
#if IS_ENABLED(CONFIG_SAMSUNG_NFC)
#define PLATFORM_DEFAULT_GPIO_CNT 3
#endif
/* NFC GPIO variables */
struct platform_gpio {
int irq;
int ven;
int dwl_req;
#if IS_ENABLED(CONFIG_SAMSUNG_NFC)
int clk_req;
int clk_req_irq;
bool clk_req_irq_enabled;
#endif
};
/* NFC Struct to get all the required configs from DTS */
struct platform_configs {
struct platform_gpio gpio;
#if IS_ENABLED(CONFIG_SAMSUNG_NFC)
bool clk_req_wake;
bool clk_req_all_trigger;
bool change_clkreq_for_acpm;
int ap_vendor;
struct regulator *nfc_pvdd;
struct clk *nfc_clock;
bool late_pvdd_en;
bool disable_clk_irq_during_wakeup;
struct notifier_block ldo_ocp_nb;
#if IS_ENABLED(CONFIG_SEC_NFC_EINT_EXYNOS)
bool clk_req_eint_mode;
#endif
#endif
};
/* cold reset Features specific Parameters */
struct cold_reset {
bool rsp_pending; /* cmd rsp pending status */
bool in_progress; /* for cold reset when gurad timer in progress */
bool reset_protection; /* reset protection enabled/disabled */
uint8_t status; /* status from response buffer */
uint8_t rst_prot_src; /* reset protection source (SPI, NFC) */
struct timer_list timer;
wait_queue_head_t read_wq;
};
/* Device specific structure */
struct nfc_dev {
wait_queue_head_t read_wq;
struct mutex read_mutex;
struct mutex write_mutex;
uint8_t *read_kbuf;
uint8_t *write_kbuf;
struct mutex dev_ref_mutex;
unsigned int dev_ref_count;
struct class *nfc_class;
struct device *nfc_device;
struct cdev c_dev;
dev_t devno;
/* Interface flag */
uint8_t interface;
/* nfc state flags */
uint8_t nfc_state;
/* NFC VEN pin state */
bool nfc_ven_enabled;
bool release_read;
union {
struct i2c_dev i2c_dev;
};
struct platform_configs configs;
struct cold_reset cold_reset;
#if IS_ENABLED(CONFIG_SAMSUNG_NFC)
struct nfc_wake_lock nfc_wake_lock;
struct nfc_wake_lock nfc_clk_wake_lock;
bool clk_req_wakelock;
bool screen_cfg;
bool screen_on_cmd;
bool screen_off_cmd;
int screen_off_rsp_count;
struct notifier_block reboot_nb;
#endif
/* function pointers for the common i2c functionality */
int (*nfc_read)(struct nfc_dev *dev, char *buf, size_t count,
int timeout);
int (*nfc_write)(struct nfc_dev *dev, const char *buf,
const size_t count, int max_retry_cnt);
int (*nfc_enable_intr)(struct nfc_dev *dev);
int (*nfc_disable_intr)(struct nfc_dev *dev);
#if IS_ENABLED(CONFIG_SAMSUNG_NFC)
void (*nfc_enable_clk_intr)(struct nfc_dev *dev);
void (*nfc_disable_clk_intr)(struct nfc_dev *dev);
#endif
};
int nfc_dev_open(struct inode *inode, struct file *filp);
int nfc_dev_flush(struct file *pfile, fl_owner_t id);
int nfc_dev_close(struct inode *inode, struct file *filp);
long nfc_dev_compat_ioctl(struct file *pfile, unsigned int cmd,
unsigned long arg);
long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg);
int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs,
uint8_t interface);
int nfc_misc_register(struct nfc_dev *nfc_dev,
const struct file_operations *nfc_fops, int count,
char *devname, char *classname);
void nfc_misc_unregister(struct nfc_dev *nfc_dev, int count);
int configure_gpio(unsigned int gpio, int flag);
void gpio_set_ven(struct nfc_dev *nfc_dev, int value);
void gpio_free_all(struct nfc_dev *nfc_dev);
int validate_nfc_state_nci(struct nfc_dev *nfc_dev);
#if IS_ENABLED(CONFIG_SAMSUNG_NFC)
int nfc_regulator_onoff(struct nfc_dev *nfc_dev, int onoff);
void nfc_power_control(struct nfc_dev *nfc_dev);
void nfc_print_status(void);
void nfc_probe_done(struct nfc_dev *nfc_dev);
bool nfc_check_pvdd_status(void);
enum lpm_status nfc_get_lpcharge(void);
#ifdef CONFIG_MAKE_NODE_USING_PLATFORM_DEVICE
void nfc_parse_dt_for_platform_device(struct device *dev);
#endif
#endif
#endif /* _COMMON_H_ */