mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 20:33:58 -04:00
dlkm: add new silead fps driver
Silead fingerprint sensor is a new chipset and vendor Add new driver to support it. Change-Id: Ibbad53b820b527e4d4e42af9c6f7ec5718d1d6dd Signed-off-by: wuwl10 <wuwl10@motorola.com> Reviewed-on: https://gerrit.mot.com/2062795 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Ling Zhong <zhongl1@motorola.com> Reviewed-by: Yan Zhang <zhangy26@motorola.com> Reviewed-by: Hujun Liao <liaohj@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
853d4cf831
commit
0411fbfbcd
7 changed files with 2560 additions and 0 deletions
15
drivers/input/misc/silead_fps_mmi/Android.mk
Normal file
15
drivers/input/misc/silead_fps_mmi/Android.mk
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
DLKM_DIR := motorola/kernel/modules
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
ifeq ($(DLKM_INSTALL_TO_VENDOR_OUT),true)
|
||||
SILEAD_FPS_MMI_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/
|
||||
else
|
||||
SILEAD_FPS_MMI_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
endif
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := silead_fps_mmi.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(SILEAD_FPS_MMI_MODULE_PATH)
|
||||
include $(DLKM_DIR)/AndroidKernelModule.mk
|
||||
|
||||
21
drivers/input/misc/silead_fps_mmi/Kbuild
Normal file
21
drivers/input/misc/silead_fps_mmi/Kbuild
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# add -Wall to try to catch everything we can.
|
||||
EXTRA_CFLAGS += -Wall
|
||||
EXTRA_CFLAGS += -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include
|
||||
|
||||
ifdef CONFIG_ARCH_MSM
|
||||
ccflags-y += -DBSP_SIL_PLAT_QCOM
|
||||
endif
|
||||
|
||||
ifdef CONFIG_ARCH_QCOM
|
||||
ccflags-y += -DBSP_SIL_PLAT_QCOM
|
||||
endif
|
||||
|
||||
ifdef CONFIG_ARCH_SPRD
|
||||
ccflags-y += -DBSP_SIL_PLAT_SPRD
|
||||
endif
|
||||
|
||||
silead_fps_mmi-y += silead_fp.o
|
||||
|
||||
|
||||
obj-m += silead_fps_mmi.o
|
||||
|
||||
10
drivers/input/misc/silead_fps_mmi/Makefile
Normal file
10
drivers/input/misc/silead_fps_mmi/Makefile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
|
||||
1543
drivers/input/misc/silead_fps_mmi/silead_fp.c
Normal file
1543
drivers/input/misc/silead_fps_mmi/silead_fp.c
Normal file
File diff suppressed because it is too large
Load diff
316
drivers/input/misc/silead_fps_mmi/silead_fp.h
Normal file
316
drivers/input/misc/silead_fps_mmi/silead_fp.h
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* @file silead_fp.h
|
||||
* @brief Contains silead_fp device head file.
|
||||
*
|
||||
*
|
||||
* Copyright 2016-2021 GigaDevice/Silead Inc.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* ------------------- Revision History ------------------------------
|
||||
* <author> <date> <version> <desc>
|
||||
* Bill Yu 2018/5/2 0.1.0 Init version
|
||||
* Bill Yu 2018/5/28 0.1.1 Disable netlink if netlink id = 0
|
||||
* Bill Yu 2018/6/1 0.1.2 Support wakelock
|
||||
* Bill Yu 2018/6/5 0.1.3 Support chip enter power down
|
||||
* Bill Yu 2018/6/7 0.1.4 Support create proc node
|
||||
* Bill Yu 2018/6/27 0.1.5 Expand pwdn I/F
|
||||
* Rui Wu 2019/10/10 0.1.6 Support create class node
|
||||
* Bill Yu 2020/5/11 0.1.7 Netlink id should < 32
|
||||
* Bill Yu 2020/5/29 0.1.8 Default use poll
|
||||
* Bill Yu 2020/12/22 0.1.9 Support 5.x version wakeup
|
||||
* Melvin cao 2021/01/29 0.2.0 Support silead spi device driver
|
||||
*/
|
||||
|
||||
#ifndef __SILEAD_FP_H__
|
||||
#define __SILEAD_FP_H__
|
||||
|
||||
#include <linux/printk.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#ifndef _LINUX_WAKELOCK_H
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
|
||||
#define USE_WAKEUP_REG
|
||||
#endif
|
||||
|
||||
enum {
|
||||
WAKE_LOCK_SUSPEND, /* Prevent suspend */
|
||||
WAKE_LOCK_TYPE_COUNT
|
||||
};
|
||||
|
||||
#ifdef USE_WAKEUP_REG
|
||||
struct wake_lock {
|
||||
struct wakeup_source *ws;
|
||||
};
|
||||
|
||||
#define ws_init(s, n) s = wakeup_source_register(NULL, n)
|
||||
#define ws_deinit(s) wakeup_source_unregister(s)
|
||||
#define ws_lock(s) __pm_stay_awake(s)
|
||||
#define ws_lock_tm(s, t) __pm_wakeup_event(s, t)
|
||||
#define ws_unlock(s) __pm_relax(s)
|
||||
|
||||
#else
|
||||
struct wake_lock {
|
||||
struct wakeup_source ws;
|
||||
};
|
||||
|
||||
#define ws_init(s, n) wakeup_source_init(&s, n)
|
||||
#define ws_deinit(s) wakeup_source_trash(&s)
|
||||
#define ws_lock(s) __pm_stay_awake(&s)
|
||||
#define ws_lock_tm(s, t) __pm_wakeup_event(&s, t)
|
||||
#define ws_unlock(s) __pm_relax(&s)
|
||||
|
||||
#endif /* USE_WAKEUP_REG */
|
||||
|
||||
static inline void wake_lock_init(struct wake_lock *lock, int type,
|
||||
const char *name)
|
||||
{
|
||||
ws_init(lock->ws, name);
|
||||
}
|
||||
|
||||
static inline void wake_lock_destroy(struct wake_lock *lock)
|
||||
{
|
||||
ws_deinit(lock->ws);
|
||||
}
|
||||
|
||||
static inline void wake_lock(struct wake_lock *lock)
|
||||
{
|
||||
ws_lock(lock->ws);
|
||||
}
|
||||
|
||||
static inline void wake_lock_timeout(struct wake_lock *lock, long timeout)
|
||||
{
|
||||
ws_lock_tm(lock->ws, jiffies_to_msecs(timeout));
|
||||
}
|
||||
|
||||
static inline void wake_unlock(struct wake_lock *lock)
|
||||
{
|
||||
ws_unlock(lock->ws);
|
||||
}
|
||||
#endif /* _LINUX_WAKELOCK_H */
|
||||
|
||||
enum _pwdn_mode_t {
|
||||
SIFP_PWDN_NONE = 0,
|
||||
SIFP_PWDN_POWEROFF = 1, /* shutdown the avdd power supply */
|
||||
SIFP_PWDN_FLASH = 2, /* shutdown avdd 200ms for H/W full reset */
|
||||
SIFP_PWDN_MAX,
|
||||
};
|
||||
|
||||
enum _netlink_cmd_t {
|
||||
SIFP_NETLINK_START = 0,
|
||||
SIFP_NETLINK_IRQ = 1,
|
||||
SIFP_NETLINK_SCR_OFF,
|
||||
SIFP_NETLINK_SCR_ON,
|
||||
SIFP_NETLINK_CONNECT,
|
||||
SIFP_NETLINK_DISCONNECT,
|
||||
SIFP_NETLINK_TP_TOUCHDOWN,
|
||||
SIFP_NETLINK_TP_TOUCHUP,
|
||||
SIFP_NETLINK_MAX,
|
||||
};
|
||||
|
||||
enum _fp_nav_key_v_t {
|
||||
NAV_KEY_UNKNOWN = 0,
|
||||
NAV_KEY_START = 1,
|
||||
NAV_KEY_UP = NAV_KEY_START,
|
||||
NAV_KEY_DOWN,
|
||||
NAV_KEY_RIGHT,
|
||||
NAV_KEY_LEFT,
|
||||
NAV_KEY_CLICK,
|
||||
NAV_KEY_DCLICK,
|
||||
NAV_KEY_LONGPRESS,
|
||||
NAV_KEY_CLICK_DOWN,
|
||||
NAV_KEY_CLICK_UP,
|
||||
NAV_KEY_MAX,
|
||||
NAV_KEY_WAITMORE = 1000,
|
||||
};
|
||||
|
||||
#define IS_KEY_VALID(k) ((k) > NAV_KEY_UNKNOWN && (k) < NAV_KEY_MAX)
|
||||
|
||||
enum _fp_nav_key_f_t {
|
||||
NAV_KEY_FLAG_UP = 0,
|
||||
NAV_KEY_FLAG_DOWN,
|
||||
NAV_KEY_FLAG_CLICK,
|
||||
};
|
||||
|
||||
struct fp_dev_key_t {
|
||||
int value;
|
||||
uint32_t flag; /* key down = 1, key up = 0, key down+up = 2 */
|
||||
};
|
||||
|
||||
#define DEVNAME_LEN 16
|
||||
struct fp_dev_init_t {
|
||||
uint8_t mode;
|
||||
uint8_t bits;
|
||||
uint16_t delay;
|
||||
uint32_t speed;
|
||||
char dev[DEVNAME_LEN];
|
||||
uint8_t nl_id;
|
||||
uint8_t dev_id;
|
||||
uint16_t reserve;
|
||||
uint32_t reg;
|
||||
char ta[DEVNAME_LEN];
|
||||
};
|
||||
|
||||
struct fp_dev_debug_t {
|
||||
uint8_t cmd[4];
|
||||
};
|
||||
|
||||
struct fp_dev_kmap_t {
|
||||
uint16_t k[NAV_KEY_MAX-NAV_KEY_START]; /* Up/Down/Right/Left/Click/Double Click/Longpress */
|
||||
};
|
||||
|
||||
struct fp_dev_touch_info {
|
||||
uint8_t touch_state;
|
||||
uint8_t area_rate;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
};
|
||||
|
||||
#define PROC_VND_ID_LEN 32
|
||||
|
||||
#define SIFP_IOC_MAGIC 's'
|
||||
|
||||
#define SIFP_IOC_RESET _IOW(SIFP_IOC_MAGIC, 10, u8)
|
||||
|
||||
#define SIFP_IOC_ENABLE_IRQ _IO(SIFP_IOC_MAGIC, 11)
|
||||
#define SIFP_IOC_DISABLE_IRQ _IO(SIFP_IOC_MAGIC, 12)
|
||||
#define SIFP_IOC_WAIT_IRQ _IOR(SIFP_IOC_MAGIC, 13, u8)
|
||||
#define SIFP_IOC_CLR_IRQ _IO(SIFP_IOC_MAGIC, 14)
|
||||
//#define SPFP_IOC_EXIT _IOR(SIFP_IOC_MAGIC, 1, u8)
|
||||
|
||||
#define SIFP_IOC_KEY_EVENT _IOW(SIFP_IOC_MAGIC, 15, struct fp_dev_key_t)
|
||||
#define SIFP_IOC_INIT _IOR(SIFP_IOC_MAGIC, 16, struct fp_dev_init_t)
|
||||
#define SIFP_IOC_DEINIT _IO(SIFP_IOC_MAGIC, 17)
|
||||
#define SIFP_IOC_IRQ_STATUS _IOR(SIFP_IOC_MAGIC, 18, u8)
|
||||
#define SIFP_IOC_DEBUG _IOR(SIFP_IOC_MAGIC, 19, struct fp_dev_debug_t)
|
||||
#define SIFP_IOC_SCR_STATUS _IOR(SIFP_IOC_MAGIC, 20, u8)
|
||||
#define SIFP_IOC_GET_VER _IOR(SIFP_IOC_MAGIC, 21, char[10])
|
||||
#define SIFP_IOC_SET_KMAP _IOW(SIFP_IOC_MAGIC, 22, uint16_t[7])
|
||||
#define SIFP_IOC_ACQ_SPI _IO(SIFP_IOC_MAGIC, 23)
|
||||
#define SIFP_IOC_RLS_SPI _IO(SIFP_IOC_MAGIC, 24)
|
||||
#define SIFP_IOC_PKG_SIZE _IOR(SIFP_IOC_MAGIC, 25, u8)
|
||||
#define SIFP_IOC_DBG_LEVEL _IOWR(SIFP_IOC_MAGIC,26, u8)
|
||||
#define SIFP_IOC_WAKELOCK _IOW(SIFP_IOC_MAGIC, 27, u8)
|
||||
#define SIFP_IOC_PWDN _IOW(SIFP_IOC_MAGIC, 28, u8)
|
||||
#define SIFP_IOC_PROC_NODE _IOW(SIFP_IOC_MAGIC, 29, char[PROC_VND_ID_LEN])
|
||||
#define SIFP_IOC_SET_FEATURE _IOW(SIFP_IOC_MAGIC, 30, u8)
|
||||
|
||||
#define FEATURE_FLASH_CS 0x01
|
||||
|
||||
#define RESET_TIME 2 /* Default chip reset wait time(ms) */
|
||||
#define RESET_TIME_MULTIPLE 1 /* Multiple for reset time multiple*wait_time */
|
||||
#define SIFP_NETLINK_ROUTE 0 /* 0: poll/1-31: netlink(cat /proc/net/netlink)/ > 31: epoll/ 30 */
|
||||
#define NL_MSG_LEN 16
|
||||
|
||||
//#define PROC_DIR "fp" /* if defined, create node under /proc/fp/xxx */
|
||||
#define PROC_NODE "fp_id" /* proc node name */
|
||||
|
||||
//#define CLASS_NODE "fingerprint" /* if defined, create class node /sys/class/fingerprint/fingerprint */
|
||||
|
||||
#if (SIFP_NETLINK_ROUTE > 0) && (SIFP_NETLINK_ROUTE < 32)
|
||||
#define BSP_SIL_NETLINK
|
||||
#endif
|
||||
|
||||
#if !defined(BSP_SIL_PLAT_MTK) && !defined(BSP_SIL_PLAT_QCOM)
|
||||
#define BSP_SIL_PLAT_COMM
|
||||
#endif /* ! BSP_SIL_PLAT_MTK & ! BSP_SIL_PLAT_QCOM */
|
||||
|
||||
/* Todo: enable correct power supply mode */
|
||||
//#define BSP_SIL_POWER_SUPPLY_REGULATOR
|
||||
//#define BSP_SIL_POWER_SUPPLY_PINCTRL
|
||||
#define BSP_SIL_POWER_SUPPLY_GPIO
|
||||
|
||||
/* AVDD voltage range 2.8v ~ 3.3v */
|
||||
#define AVDD_MAX 2800000
|
||||
#define AVDD_MIN 2800000
|
||||
|
||||
/* VDDIO voltage range 1.8v ~ AVDD */
|
||||
#define VDDIO_MAX 1800000
|
||||
#define VDDIO_MIN 1800000
|
||||
|
||||
#if defined(BSP_SIL_POWER_SUPPLY_REGULATOR) && defined(BSP_SIL_POWER_SUPPLY_PINCTRL) || defined(BSP_SIL_POWER_SUPPLY_REGULATOR) && defined(BSP_SIL_POWER_SUPPLY_GPIO) || defined(BSP_SIL_POWER_SUPPLY_GPIO) && defined(BSP_SIL_POWER_SUPPLY_PINCTRL)
|
||||
#error "Don't define multiple power supply mode!"
|
||||
#endif
|
||||
|
||||
#ifdef BSP_SIL_PLAT_MTK
|
||||
#include "silead_fp_mtk.h"
|
||||
#define PLAT_H "silead_fp_mtk.c"
|
||||
#define SILFP_SPI_REE /* REE silead_spi driver, disable it if CONFIG_SPIDEV is enabled */
|
||||
|
||||
#ifdef SILFP_SPI_REE
|
||||
#define DEVICE "/dev/silead_spi"
|
||||
#else
|
||||
#define DEVICE "/dev/spidev1.0"
|
||||
#endif
|
||||
//#define BSP_SIL_IRQ_CONFIRM
|
||||
#define PKG_SIZE 1
|
||||
#define BSP_SIL_DYNAMIC_SPI
|
||||
#ifndef CONFIG_SILEAD_FP_PLATFORM
|
||||
#define BSP_SIL_CTRL_SPI
|
||||
#endif /* !CONFIG_SILEAD_FP_PLATFORM */
|
||||
#elif defined(BSP_SIL_PLAT_QCOM)
|
||||
#define QSEE_V4 /* Enable it if QSEE v4 or higher */
|
||||
#include "silead_fp_qcom.h"
|
||||
#define PLAT_H "silead_fp_qcom.c"
|
||||
|
||||
#define DEVICE "/dev/spidev0.0"
|
||||
//#define BSP_SIL_IRQ_CONFIRM
|
||||
#define PKG_SIZE 4
|
||||
#define TANAME "sileadta"
|
||||
#elif defined(BSP_SIL_PLAT_SPRD)
|
||||
#include "silead_fp_sprd.h"
|
||||
#define PLAT_H "silead_fp_sprd.c"
|
||||
|
||||
#define DEVICE "/dev/spidev0.0"
|
||||
//#define BSP_SIL_IRQ_CONFIRM
|
||||
//#define BSP_SIL_QCOM_SPECIAL
|
||||
#define PKG_SIZE 4
|
||||
#define TANAME "silead"
|
||||
#else
|
||||
#include "silead_fp_comm.h"
|
||||
#define PLAT_H "silead_fp_comm.c"
|
||||
|
||||
#define DEVICE "/dev/spidev0.0"
|
||||
//#define BSP_SIL_IRQ_CONFIRM
|
||||
#define PKG_SIZE 4
|
||||
#define TANAME ""
|
||||
#endif /* BSP_SIL_PLAT_XXX */
|
||||
|
||||
#ifdef BSP_SIL_QCOM_SPECIAL
|
||||
#define SIL_EVENT_BLANK MSM_DRM_EARLY_EVENT_BLANK
|
||||
#define SIL_EVENT_UNBLANK MSM_DRM_BLANK_UNBLANK
|
||||
#define SIL_EVENT_POWERDOWN MSM_DRM_BLANK_POWERDOWN
|
||||
#define SIL_REGISTER_CLIENT(a) do{ msm_drm_register_client(a); }while(0)
|
||||
#else
|
||||
#define SIL_EVENT_BLANK FB_EVENT_BLANK
|
||||
#define SIL_EVENT_UNBLANK FB_BLANK_UNBLANK
|
||||
#define SIL_EVENT_POWERDOWN FB_BLANK_POWERDOWN
|
||||
#define SIL_REGISTER_CLIENT(a) do{ fb_register_client(a); }while(0)
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* debug settings */
|
||||
/* -------------------------------------------------------------------- */
|
||||
typedef enum {
|
||||
ERR_LOG=0,
|
||||
INFO_LOG,
|
||||
DBG_LOG,
|
||||
ALL_LOG,
|
||||
} fp_debug_level_t;
|
||||
|
||||
#define LOG_TAG "[+silead_fp-] "
|
||||
#define LOG_MSG_DEBUG(level, fmt, args...) do { \
|
||||
if (sil_debug_level >= level) {\
|
||||
pr_warn(LOG_TAG fmt, ##args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* __SILEAD_FP_H__ */
|
||||
|
||||
/* End of file silead_fp.h */
|
||||
603
drivers/input/misc/silead_fps_mmi/silead_fp_qcom.c
Normal file
603
drivers/input/misc/silead_fps_mmi/silead_fp_qcom.c
Normal file
|
|
@ -0,0 +1,603 @@
|
|||
/*
|
||||
* @file silead_fp_qcom.c
|
||||
* @brief Contains silead_fp device implements for Qualcomm platform.
|
||||
*
|
||||
*
|
||||
* Copyright 2016-2021 Gigadevice/Silead Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License);
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ------------------- Revision History ------------------------------
|
||||
* <author> <date> <version> <desc>
|
||||
* Bill Yu 2018/5/2 0.1.0 Init version
|
||||
* Bill Yu 2018/5/20 0.1.1 Default wait 3ms after reset
|
||||
* Bill Yu 2018/6/5 0.1.2 Support chip enter power down
|
||||
* Bill Yu 2018/6/27 0.1.3 Expand pwdn I/F
|
||||
* Taobb 2019/6/6 0.1.4 Expand feature interface, irq pin set to reset pin
|
||||
* Bill Yu 2020/12/16 0.1.5 Allow GPIO ID number to be zero
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef BSP_SIL_PLAT_QCOM
|
||||
|
||||
#ifndef __SILEAD_FP_QCOM__
|
||||
#define __SILEAD_FP_QCOM__
|
||||
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#ifndef INIT_COMPLETION
|
||||
#define INIT_COMPLETION(x) ((x).done = 0)
|
||||
#endif /* INIT_COMPLETION */
|
||||
/* Qualcomm MNC platform, need define this. */
|
||||
#define reinit_completion(x) INIT_COMPLETION(*(x))
|
||||
|
||||
#define SPI_PINCTRL_STATE_DEFAULT "spi_default"
|
||||
#define SPI_PINCTRL_STATE_SLEEP "spi_sleep"
|
||||
|
||||
static irqreturn_t silfp_irq_handler(int irq, void *dev_id);
|
||||
static void silfp_work_func(struct work_struct *work);
|
||||
static int silfp_input_init(struct silfp_data *fp_dev);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* power supply */
|
||||
/* -------------------------------------------------------------------- */
|
||||
static void silfp_hw_poweron(struct silfp_data *fp_dev)
|
||||
{
|
||||
int err = 0;
|
||||
LOG_MSG_DEBUG(INFO_LOG, "[%s] enter.\n", __func__);
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_REGULATOR
|
||||
/* Power control by Regulators(LDO) */
|
||||
if ( fp_dev->avdd_ldo ) {
|
||||
err = regulator_set_voltage(fp_dev->avdd_ldo, AVDD_MIN, AVDD_MAX); /*set 2.8v*/
|
||||
err = regulator_enable(fp_dev->avdd_ldo); /*enable regulator*/
|
||||
//pmic_set_register_value(PMIC_RG_VCAMA_CAL,0x0A);
|
||||
}
|
||||
if ( fp_dev->vddio_ldo ) {
|
||||
err = regulator_set_voltage(fp_dev->vddio_ldo, VDDIO_MIN, VDDIO_MAX); /*set 1.8v*/
|
||||
err = regulator_enable(fp_dev->vddio_ldo); /*enable regulator*/
|
||||
//pmic_set_register_value(PMIC_RG_VCAMA_CAL,0x0A);
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_REGULATOR */
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_PINCTRL
|
||||
/* Power control by GPIOs */
|
||||
if ( fp_dev->pin.pins_avdd_h ) {
|
||||
err = pinctrl_select_state(fp_dev->pin.pinctrl, fp_dev->pin.pins_avdd_h);
|
||||
}
|
||||
if ( fp_dev->pin.pins_vddio_h ) {
|
||||
err = pinctrl_select_state(fp_dev->pin.pinctrl, fp_dev->pin.pins_vddio_h);
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_PINCTRL */
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_GPIO
|
||||
if ( fp_dev->avdd_port >= 0 ) {
|
||||
err = gpio_direction_output(fp_dev->avdd_port, 1);
|
||||
}
|
||||
if ( fp_dev->vddio_port >= 0 ) {
|
||||
err = gpio_direction_output(fp_dev->vddio_port, 1);
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_GPIO */
|
||||
fp_dev->power_is_off = 0;
|
||||
LOG_MSG_DEBUG(INFO_LOG, "%s: power supply ret:%d \n", __func__, err);
|
||||
}
|
||||
|
||||
static void silfp_hw_poweroff(struct silfp_data *fp_dev)
|
||||
{
|
||||
LOG_MSG_DEBUG(INFO_LOG, "[%s] enter.\n", __func__);
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_REGULATOR
|
||||
/* Power control by Regulators(LDO) */
|
||||
if ( fp_dev->avdd_ldo && (regulator_is_enabled(fp_dev->avdd_ldo) > 0)) {
|
||||
regulator_disable(fp_dev->avdd_ldo); /*disable regulator*/
|
||||
}
|
||||
if ( fp_dev->vddio_ldo && (regulator_is_enabled(fp_dev->vddio_ldo) > 0)) {
|
||||
regulator_disable(fp_dev->vddio_ldo); /*disable regulator*/
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_REGULATOR */
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_PINCTRL
|
||||
/* Power control by GPIOs */
|
||||
//fp_dev->pin.pins_avdd_h = NULL;
|
||||
//fp_dev->pin.pins_vddio_h = NULL;
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_PINCTRL */
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_GPIO
|
||||
if ( fp_dev->avdd_port >= 0 ) {
|
||||
gpio_direction_output(fp_dev->avdd_port, 0);
|
||||
}
|
||||
if ( fp_dev->vddio_port >= 0 ) {
|
||||
gpio_direction_output(fp_dev->vddio_port, 0);
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_GPIO */
|
||||
fp_dev->power_is_off = 1;
|
||||
}
|
||||
|
||||
static void silfp_power_deinit(struct silfp_data *fp_dev)
|
||||
{
|
||||
LOG_MSG_DEBUG(INFO_LOG, "[%s] enter.\n", __func__);
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_REGULATOR
|
||||
/* Power control by Regulators(LDO) */
|
||||
if ( fp_dev->avdd_ldo ) {
|
||||
regulator_disable(fp_dev->avdd_ldo); /*disable regulator*/
|
||||
regulator_put(fp_dev->avdd_ldo);
|
||||
fp_dev->avdd_ldo = NULL;
|
||||
}
|
||||
if ( fp_dev->vddio_ldo ) {
|
||||
regulator_disable(fp_dev->vddio_ldo); /*disable regulator*/
|
||||
regulator_put(fp_dev->vddio_ldo);
|
||||
fp_dev->vddio_ldo = NULL;
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_REGULATOR */
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_PINCTRL
|
||||
/* Power control by GPIOs */
|
||||
fp_dev->pin.pins_avdd_h = NULL;
|
||||
fp_dev->pin.pins_vddio_h = NULL;
|
||||
if (fp_dev->pin.pinctrl) {
|
||||
devm_pinctrl_put(fp_dev->pin.pinctrl);
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_PINCTRL */
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_GPIO
|
||||
if ( fp_dev->avdd_port >= 0 ) {
|
||||
gpio_direction_output(fp_dev->avdd_port, 0);
|
||||
gpio_free(fp_dev->avdd_port);
|
||||
fp_dev->avdd_port = -1;
|
||||
}
|
||||
if ( fp_dev->vddio_port >= 0 ) {
|
||||
gpio_direction_output(fp_dev->vddio_port, 0);
|
||||
gpio_free(fp_dev->vddio_port);
|
||||
fp_dev->vddio_port = -1;
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_GPIO */
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* hardware reset */
|
||||
/* -------------------------------------------------------------------- */
|
||||
static void silfp_hw_reset(struct silfp_data *fp_dev, u8 delay)
|
||||
{
|
||||
LOG_MSG_DEBUG(INFO_LOG, "[%s] enter, port=%d\n", __func__, fp_dev->rst_port);
|
||||
|
||||
if ( fp_dev->rst_port >= 0 ) {
|
||||
gpio_direction_output(fp_dev->rst_port, 0);
|
||||
if (fp_dev->irq_no_use && fp_dev->int_port >= 0) {
|
||||
gpio_direction_output(fp_dev->int_port, 1);
|
||||
}
|
||||
mdelay((delay?delay:5)*RESET_TIME_MULTIPLE);
|
||||
gpio_direction_output(fp_dev->rst_port, 1);
|
||||
if (fp_dev->irq_no_use && fp_dev->int_port >= 0) {
|
||||
gpio_direction_output(fp_dev->int_port, 0);
|
||||
}
|
||||
|
||||
mdelay((delay?delay:3)*RESET_TIME_MULTIPLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* power down */
|
||||
/* -------------------------------------------------------------------- */
|
||||
static void silfp_pwdn(struct silfp_data *fp_dev, u8 flag_avdd)
|
||||
{
|
||||
LOG_MSG_DEBUG(INFO_LOG, "[%s] enter, port=%d\n", __func__, fp_dev->rst_port);
|
||||
|
||||
if (SIFP_PWDN_FLASH == flag_avdd) {
|
||||
silfp_hw_poweroff(fp_dev);
|
||||
msleep(200*RESET_TIME_MULTIPLE);
|
||||
silfp_hw_poweron(fp_dev);
|
||||
}
|
||||
|
||||
if ( fp_dev->rst_port >= 0 ) {
|
||||
gpio_direction_output(fp_dev->rst_port, 0);
|
||||
if (fp_dev->irq_no_use && fp_dev->int_port >= 0) {
|
||||
gpio_direction_output(fp_dev->int_port, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (SIFP_PWDN_POWEROFF == flag_avdd) {
|
||||
silfp_hw_poweroff(fp_dev);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* init/deinit functions */
|
||||
/* -------------------------------------------------------------------- */
|
||||
static int silfp_parse_dts(struct silfp_data* fp_dev)
|
||||
{
|
||||
int ret;
|
||||
#ifndef QSEE_V4
|
||||
/* Get the pinctrl node */
|
||||
fp_dev->pin.pinctrl = devm_pinctrl_get(&fp_dev->spi->dev);
|
||||
if (IS_ERR_OR_NULL(fp_dev->pin.pinctrl)) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: Failed to get pinctrl\n", __func__);
|
||||
return PTR_ERR(fp_dev->pin.pinctrl);
|
||||
}
|
||||
|
||||
/* Get the active setting */
|
||||
fp_dev->pin.active = pinctrl_lookup_state(fp_dev->pin.pinctrl, SPI_PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR_OR_NULL(fp_dev->pin.active)) {
|
||||
fp_dev->pin.active = NULL;
|
||||
fp_dev->pin.pinctrl = NULL;
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: Failed to get pinctrl state active\n",__func__);
|
||||
return PTR_ERR(fp_dev->pin.active);
|
||||
}
|
||||
|
||||
/* Get power settings */
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_PINCTRL
|
||||
fp_dev->pin.pins_avdd_h = pinctrl_lookup_state(fp_dev->pin.pinctrl, "avdd-enable");
|
||||
if (IS_ERR_OR_NULL(fp_dev->pin.pins_avdd_h)) {
|
||||
fp_dev->pin.pins_avdd_h = NULL;
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s can't find silfp avdd-enable\n", __func__);
|
||||
// Ignore error
|
||||
}
|
||||
|
||||
fp_dev->pin.pins_vddio_h = pinctrl_lookup_state(fp_dev->pin.pinctrl, "vddio-enable");
|
||||
if (IS_ERR_OR_NULL(fp_dev->pin.pins_vddio_h)) {
|
||||
fp_dev->pin.pins_vddio_h = NULL;
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s can't find silfp vddio-enable\n", __func__);
|
||||
// Ignore error
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_PINCTRL */
|
||||
#endif /* QSEE_V4 */
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_REGULATOR
|
||||
// Todo: use correct settings.
|
||||
fp_dev->avdd_ldo = regulator_get(&fp_dev->spi->dev, "avdd");
|
||||
fp_dev->vddio_ldo= regulator_get(&fp_dev->spi->dev, "vddio");
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_REGULATOR */
|
||||
|
||||
#ifndef QSEE_V4
|
||||
/* Get sleep settings */
|
||||
fp_dev->pin.sleep = pinctrl_lookup_state(fp_dev->pin.pinctrl, SPI_PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR_OR_NULL(fp_dev->pin.sleep)) {
|
||||
fp_dev->pin.active = NULL;
|
||||
fp_dev->pin.pinctrl = NULL;
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: Failed to get pinctrl state sleep\n",__func__);
|
||||
return PTR_ERR(fp_dev->pin.sleep);
|
||||
}
|
||||
|
||||
/* Get iface_clk info */
|
||||
fp_dev->pin.iface_clk = clk_get(&fp_dev->spi->dev, "iface_clk");
|
||||
if (IS_ERR(fp_dev->pin.iface_clk)) {
|
||||
fp_dev->pin.active = NULL;
|
||||
fp_dev->pin.pinctrl = NULL;
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: Failed to get iface_clk %ld\n", __func__, PTR_ERR(fp_dev->pin.iface_clk));
|
||||
return PTR_ERR(fp_dev->pin.iface_clk);
|
||||
}
|
||||
|
||||
/* Get core_clk info */
|
||||
fp_dev->pin.core_clk = clk_get(&fp_dev->spi->dev, "core_clk");
|
||||
if (IS_ERR(fp_dev->pin.core_clk)) {
|
||||
fp_dev->pin.active = NULL;
|
||||
fp_dev->pin.pinctrl = NULL;
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: Failed to get core_clk %p\n", __func__, fp_dev->pin.core_clk);
|
||||
return PTR_ERR(fp_dev->pin.core_clk);
|
||||
}
|
||||
#else
|
||||
/* Get the SPI Max speed */
|
||||
ret = of_property_read_u32(fp_dev->spi->dev.of_node,"spi-max-frequency", &fp_dev->pin.max_speed_hz);
|
||||
if (ret) {
|
||||
fp_dev->pin.max_speed_hz = 0;
|
||||
LOG_MSG_DEBUG(ERR_LOG, "Error getting spi max speed\n");
|
||||
}
|
||||
#endif /* QSEE_V4 */
|
||||
|
||||
/* Get the QUP ID (#1-12) */
|
||||
ret = of_property_read_u32(fp_dev->spi->dev.of_node,"qcom,qup-id", &fp_dev->pin.qup_id);
|
||||
if (ret) {
|
||||
fp_dev->pin.qup_id = 0;
|
||||
LOG_MSG_DEBUG(ERR_LOG, "Error getting qup_id\n");
|
||||
}
|
||||
|
||||
LOG_MSG_DEBUG(INFO_LOG, "[%s] done (%d).\n",__func__,ret);
|
||||
/*
|
||||
Grab SPI master lock for exclusive access
|
||||
call spi_bus_unlock to unlock the lock.
|
||||
*/
|
||||
//spi_bus_lock(fp_dev->spi->master);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef QSEE_V4
|
||||
static int spi_set_pinctrl(struct silfp_data* fp_dev, bool active)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if ( IS_ERR_OR_NULL(fp_dev->pin.pinctrl) || IS_ERR_OR_NULL(fp_dev->pin.active)) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: not support\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
if (active) { /* Change to active settings */
|
||||
ret = pinctrl_select_state(fp_dev->pin.pinctrl, fp_dev->pin.active);
|
||||
} else {
|
||||
ret = pinctrl_select_state(fp_dev->pin.pinctrl, fp_dev->pin.sleep);
|
||||
}
|
||||
|
||||
LOG_MSG_DEBUG(INFO_LOG, "%s: pinctrl_select_state ret:%d Setting:%d\n", __func__, ret, active);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spi_set_clks(struct silfp_data* fp_dev, bool enable)
|
||||
{
|
||||
int ret = -1;
|
||||
int clk = 19200000;
|
||||
|
||||
if ( IS_ERR_OR_NULL(fp_dev->pin.pinctrl) || IS_ERR_OR_NULL(fp_dev->pin.active)) {
|
||||
LOG_MSG_DEBUG(INFO_LOG, "%s: not support\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
if (enable) {
|
||||
/* Enable the spi clocks */
|
||||
ret = clk_set_rate(fp_dev->pin.core_clk, fp_dev->spi->max_speed_hz);
|
||||
if (ret) {
|
||||
while ( clk > fp_dev->spi->max_speed_hz ) {
|
||||
clk >>= 1;
|
||||
}
|
||||
if ( clk < 4800000 ) {
|
||||
clk = 4800000;
|
||||
}
|
||||
ret = clk_set_rate(fp_dev->pin.core_clk, clk);
|
||||
if ( ret ) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: Error setting clk_rate:%d, ret=%d\n",__func__, clk,ret);
|
||||
} else {
|
||||
fp_dev->spi->max_speed_hz = clk;
|
||||
}
|
||||
}
|
||||
ret = clk_prepare_enable(fp_dev->pin.core_clk);
|
||||
if (ret) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: Error enabling core clk, ret=%d\n",__func__,ret);
|
||||
}
|
||||
ret = clk_prepare_enable(fp_dev->pin.iface_clk);
|
||||
if (ret) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: Error enabling iface clk, ret=%d\n",__func__,ret);
|
||||
}
|
||||
} else {
|
||||
/* Disable the clocks */
|
||||
clk_disable_unprepare(fp_dev->pin.iface_clk);
|
||||
clk_disable_unprepare(fp_dev->pin.core_clk);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
LOG_MSG_DEBUG(DBG_LOG, "[%s] done (%d), speed = %d.\n",__func__,ret,fp_dev->spi->max_speed_hz );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spi_set_fabric(struct silfp_data* fp_dev, bool active)
|
||||
{
|
||||
int ret;
|
||||
struct spi_master *master = fp_dev->spi->master;
|
||||
|
||||
if (active) {
|
||||
ret = master->prepare_transfer_hardware(master);
|
||||
} else {
|
||||
ret = master->unprepare_transfer_hardware(master);
|
||||
}
|
||||
LOG_MSG_DEBUG(DBG_LOG, "[%s] done (%d).\n",__func__,ret);
|
||||
return ret;
|
||||
}
|
||||
#endif /* !QSEE_V4 */
|
||||
|
||||
static int silfp_set_spi(struct silfp_data *fp_dev, bool enable)
|
||||
{
|
||||
int ret = -ENOENT;
|
||||
#ifndef QSEE_V4
|
||||
if ( IS_ERR_OR_NULL(fp_dev->pin.pinctrl) || IS_ERR_OR_NULL(fp_dev->pin.active) || !fp_dev->pin.qup_id ) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: not support!\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ( enable && !atomic_read(&fp_dev->spionoff_count) ) {
|
||||
atomic_inc(&fp_dev->spionoff_count);
|
||||
ret = spi_set_pinctrl(fp_dev, enable);
|
||||
ret |= spi_set_fabric(fp_dev, enable);
|
||||
ret |= spi_set_clks(fp_dev, enable);
|
||||
} else if (atomic_read(&fp_dev->spionoff_count)) {
|
||||
atomic_dec(&fp_dev->spionoff_count);
|
||||
//spi_change_pipe_owner(false);
|
||||
ret = spi_set_clks(fp_dev, enable);
|
||||
ret |= spi_set_fabric(fp_dev, enable);
|
||||
ret |= spi_set_pinctrl(fp_dev, enable);
|
||||
}
|
||||
#else
|
||||
LOG_MSG_DEBUG(ERR_LOG, "%s: qsee4 no needed!\n", __func__);
|
||||
#endif /* !QSEE_V4 */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int silfp_irq_to_reset_init(struct silfp_data *fp_dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
silfp_irq_disable(fp_dev);
|
||||
free_irq(fp_dev->irq, fp_dev);
|
||||
|
||||
if (fp_dev->int_port >= 0) {
|
||||
gpio_free(fp_dev->int_port);
|
||||
ret = gpio_request(fp_dev->int_port, "SILFP_IRQ_TO_RST_PIN");
|
||||
if (ret < 0) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "[%s] Failed to request GPIO=%d, ret=%d",__func__,(s32)fp_dev->int_port, ret);
|
||||
return -ENODEV;
|
||||
} else {
|
||||
gpio_direction_output(fp_dev->int_port, 0);
|
||||
}
|
||||
}
|
||||
|
||||
fp_dev->irq_no_use = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int silfp_set_feature(struct silfp_data *fp_dev, u8 feature)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (feature) {
|
||||
case FEATURE_FLASH_CS:
|
||||
LOG_MSG_DEBUG(INFO_LOG, "%s set feature flash cs\n", __func__);
|
||||
ret = silfp_irq_to_reset_init(fp_dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int silfp_resource_init(struct silfp_data *fp_dev, struct fp_dev_init_t *dev_info)
|
||||
{
|
||||
int status = 0;
|
||||
int ret;
|
||||
|
||||
LOG_MSG_DEBUG(ERR_LOG, "[%s] enter.\n", __func__);
|
||||
printk(KERN_INFO "silfp_resource_init enter!\n");
|
||||
|
||||
if (atomic_read(&fp_dev->init)) {
|
||||
atomic_inc(&fp_dev->init);
|
||||
LOG_MSG_DEBUG(DBG_LOG, "[%s] dev already init(%d).\n",__func__,atomic_read(&fp_dev->init));
|
||||
return status;
|
||||
}
|
||||
|
||||
fp_dev->int_port = -1;
|
||||
fp_dev->rst_port = -1;
|
||||
silfp_parse_dts(fp_dev);
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_GPIO
|
||||
fp_dev->avdd_port = of_get_named_gpio(fp_dev->spi->dev.of_node, "avdd-gpios", 0);
|
||||
fp_dev->vddio_port = of_get_named_gpio(fp_dev->spi->dev.of_node, "vddio-gpios", 0);
|
||||
if (fp_dev->avdd_port >= 0 ) {
|
||||
gpio_free(fp_dev->avdd_port);
|
||||
ret = gpio_request(fp_dev->avdd_port, "SILFP_AVDD_PIN");
|
||||
if (ret < 0) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "[%s] Failed to request GPIO=%d, ret=%d",__func__,(s32)fp_dev->avdd_port, ret);
|
||||
status = -ENODEV;
|
||||
goto err_avdd;
|
||||
}
|
||||
}
|
||||
|
||||
if (fp_dev->vddio_port >= 0 ) {
|
||||
gpio_free(fp_dev->vddio_port);
|
||||
ret = gpio_request(fp_dev->vddio_port, "SILFP_VDDIO_PIN");
|
||||
if (ret < 0) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "[%s] Failed to request GPIO=%d, ret=%d",__func__,(s32)fp_dev->vddio_port, ret);
|
||||
status = -ENODEV;
|
||||
//goto err_vddio;
|
||||
}
|
||||
}
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_GPIO */
|
||||
silfp_hw_poweron(fp_dev);
|
||||
fp_dev->int_port = of_get_named_gpio(fp_dev->spi->dev.of_node, "irq-gpios", 0);
|
||||
fp_dev->rst_port = of_get_named_gpio(fp_dev->spi->dev.of_node, "rst-gpios", 0);
|
||||
LOG_MSG_DEBUG(INFO_LOG, "[%s] int_port %d, rst_port %d.\n",__func__,fp_dev->int_port,fp_dev->rst_port);
|
||||
if (fp_dev->int_port >= 0 ) {
|
||||
gpio_free(fp_dev->int_port);
|
||||
}
|
||||
|
||||
if (fp_dev->rst_port >= 0 ) {
|
||||
gpio_free(fp_dev->rst_port);
|
||||
}
|
||||
|
||||
ret = gpio_request(fp_dev->int_port, "SILFP_INT_IRQ");
|
||||
if (ret < 0) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "[%s] Failed to request GPIO=%d, ret=%d",__func__,(s32)fp_dev->int_port, ret);
|
||||
status = -ENODEV;
|
||||
goto err;
|
||||
} else {
|
||||
gpio_direction_input(fp_dev->int_port);
|
||||
fp_dev->irq = gpio_to_irq(fp_dev->int_port);
|
||||
fp_dev->irq_is_disable = 0;
|
||||
|
||||
ret = request_irq(fp_dev->irq,
|
||||
silfp_irq_handler,
|
||||
IRQ_TYPE_EDGE_RISING, //IRQ_TYPE_LEVEL_HIGH, //irq_table[ts->int_trigger_type],
|
||||
"silfp",
|
||||
fp_dev);
|
||||
if ( ret < 0 ) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "[%s] Filed to request_irq (%d), ert=%d",__func__,fp_dev->irq, ret);
|
||||
status = -ENODEV;
|
||||
goto err_irq;
|
||||
} else {
|
||||
LOG_MSG_DEBUG(INFO_LOG,"[%s] Enable_irq_wake.\n",__func__);
|
||||
enable_irq_wake(fp_dev->irq);
|
||||
silfp_irq_disable(fp_dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (fp_dev->rst_port >= 0 ) {
|
||||
ret = gpio_request(fp_dev->rst_port, "SILFP_RST_PIN");
|
||||
if (ret < 0) {
|
||||
LOG_MSG_DEBUG(ERR_LOG, "[%s] Failed to request GPIO=%d, ret=%d",__func__,(s32)fp_dev->rst_port, ret);
|
||||
status = -ENODEV;
|
||||
goto err_rst;
|
||||
} else {
|
||||
gpio_direction_output(fp_dev->rst_port, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
if (silfp_input_init(fp_dev)) {
|
||||
goto err_input;
|
||||
}
|
||||
atomic_set(&fp_dev->init,1);
|
||||
}
|
||||
fp_dev->irq_no_use = 0;
|
||||
dev_info->reserve = PKG_SIZE;
|
||||
dev_info->reserve <<= 12;
|
||||
#ifdef QSEE_V4
|
||||
if (fp_dev->pin.max_speed_hz) {
|
||||
dev_info->speed = fp_dev->pin.max_speed_hz;
|
||||
}
|
||||
#endif /* QSEE_V4 */
|
||||
|
||||
if (dev_info && fp_dev->pin.qup_id && (fp_dev->pin.qup_id <= 32)) {
|
||||
dev_info->dev_id = fp_dev->pin.qup_id;
|
||||
strncpy(dev_info->ta,TANAME,sizeof(dev_info->ta));
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
err_input:
|
||||
if (fp_dev->rst_port >= 0 ) {
|
||||
gpio_free(fp_dev->rst_port);
|
||||
}
|
||||
|
||||
err_rst:
|
||||
free_irq(fp_dev->irq, fp_dev);
|
||||
gpio_direction_input(fp_dev->int_port);
|
||||
|
||||
err_irq:
|
||||
gpio_free(fp_dev->int_port);
|
||||
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_GPIO
|
||||
gpio_free(fp_dev->vddio_port);
|
||||
#if 0
|
||||
err_vddio:
|
||||
gpio_free(fp_dev->avdd_port);
|
||||
#endif
|
||||
err_avdd:
|
||||
fp_dev->avdd_port = -1;
|
||||
fp_dev->vddio_port = -1;
|
||||
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_GPIO */
|
||||
|
||||
err:
|
||||
fp_dev->int_port = -1;
|
||||
fp_dev->rst_port = -1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* __SILEAD_FP_QCOM__ */
|
||||
|
||||
#endif /* BSP_SIL_PLAT_QCOM */
|
||||
|
||||
/* End of file spilead_fp_qcom.c */
|
||||
52
drivers/input/misc/silead_fps_mmi/silead_fp_qcom.h
Normal file
52
drivers/input/misc/silead_fps_mmi/silead_fp_qcom.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* @file silead_fp_qcom.h
|
||||
* @brief Contains silead_fp Qualcomm platform specific head file.
|
||||
*
|
||||
*
|
||||
* Copyright 2016-2021 Gigadevice/Silead Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License);
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ------------------- Revision History ------------------------------
|
||||
* <author> <date> <version> <desc>
|
||||
* Bill Yu 2018/5/2 0.1.0 Init version
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SILEAD_FP_QCOM_H__
|
||||
#define __SILEAD_FP_QCOM_H__
|
||||
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
struct fp_plat_t {
|
||||
u32 qup_id;
|
||||
#ifdef QSEE_V4
|
||||
u32 max_speed_hz;
|
||||
#else
|
||||
/* pinctrl info */
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *active;
|
||||
struct pinctrl_state *sleep;
|
||||
#ifdef BSP_SIL_POWER_SUPPLY_PINCTRL
|
||||
struct pinctrl_state *pins_avdd_h, *pins_vddio_h;
|
||||
#endif /* BSP_SIL_POWER_SUPPLY_PINCTRL */
|
||||
/* clock info */
|
||||
struct clk *core_clk;
|
||||
struct clk *iface_clk;
|
||||
#endif /* QSEE_V4 */
|
||||
};
|
||||
|
||||
#endif /* __SILEAD_FP_QCOM_H__ */
|
||||
|
||||
/* End of file silead_fp_qcom.h */
|
||||
Loading…
Reference in a new issue