From ea2e8997d116b653a1887fe964acbdfddd37cd7c Mon Sep 17 00:00:00 2001 From: daiss1 Date: Mon, 29 Jun 2020 17:13:12 +0800 Subject: [PATCH] KeivJP: bringup chipone fps driver bringup chipone fps driver build fpsensor_spi_tee NO_PROP_NEEDED:chipone fps only used kiev Change-Id: If53eb500939061791959c31d5525d2f323736df2 Signed-off-by: daiss1 Reviewed-on: https://gerrit.mot.com/1649664 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- drivers/input/misc/chipone_fps_mmi/Android.mk | 9 + drivers/input/misc/chipone_fps_mmi/Kbuild | 5 + drivers/input/misc/chipone_fps_mmi/Makefile | 10 + .../misc/chipone_fps_mmi/fpsensor_spi_tee.c | 735 ++++++++++++++++++ .../misc/chipone_fps_mmi/fpsensor_spi_tee.h | 69 ++ .../misc/chipone_fps_mmi/fpsensor_wakelock.h | 68 ++ 6 files changed, 896 insertions(+) create mode 100644 drivers/input/misc/chipone_fps_mmi/Android.mk create mode 100644 drivers/input/misc/chipone_fps_mmi/Kbuild create mode 100644 drivers/input/misc/chipone_fps_mmi/Makefile create mode 100644 drivers/input/misc/chipone_fps_mmi/fpsensor_spi_tee.c create mode 100644 drivers/input/misc/chipone_fps_mmi/fpsensor_spi_tee.h create mode 100644 drivers/input/misc/chipone_fps_mmi/fpsensor_wakelock.h diff --git a/drivers/input/misc/chipone_fps_mmi/Android.mk b/drivers/input/misc/chipone_fps_mmi/Android.mk new file mode 100644 index 000000000000..bb205ebbf435 --- /dev/null +++ b/drivers/input/misc/chipone_fps_mmi/Android.mk @@ -0,0 +1,9 @@ +DLKM_DIR := motorola/kernel/modules +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := fpsensor_spi_tee.ko +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +include $(DLKM_DIR)/AndroidKernelModule.mk + diff --git a/drivers/input/misc/chipone_fps_mmi/Kbuild b/drivers/input/misc/chipone_fps_mmi/Kbuild new file mode 100644 index 000000000000..52121f562739 --- /dev/null +++ b/drivers/input/misc/chipone_fps_mmi/Kbuild @@ -0,0 +1,5 @@ +# add -Wall to try to catch everything we can. +EXTRA_CFLAGS += -Wall +EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include + +obj-m += fpsensor_spi_tee.o diff --git a/drivers/input/misc/chipone_fps_mmi/Makefile b/drivers/input/misc/chipone_fps_mmi/Makefile new file mode 100644 index 000000000000..4191dea22679 --- /dev/null +++ b/drivers/input/misc/chipone_fps_mmi/Makefile @@ -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 diff --git a/drivers/input/misc/chipone_fps_mmi/fpsensor_spi_tee.c b/drivers/input/misc/chipone_fps_mmi/fpsensor_spi_tee.c new file mode 100644 index 000000000000..0e2491b0951c --- /dev/null +++ b/drivers/input/misc/chipone_fps_mmi/fpsensor_spi_tee.c @@ -0,0 +1,735 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_COMPAT +#include +#endif + +#include "fpsensor_spi_tee.h" +#include "fpsensor_wakelock.h" +#define FPSENSOR_FB_DRM 1 +#define FPSENSOR_FB_OLD 2 + +#define FPSENSOR_WAKEUP_SOURCE 1 +#define FPSENSOR_WAKEUP_OLD 2 + +#define FPSENSOR_SPI_VERSION "fpsensor_spi_tee_qcomm_v1.23.1" +#define FPSENSOR_USE_QCOM_POWER_GPIO 0 +#define FPSENSOR_WAKEUP_TYPE FPSENSOR_WAKEUP_SOURCE +#define FP_NOTIFY 1 +#define FP_NOTIFY_TYPE FPSENSOR_FB_DRM + +#if FP_NOTIFY +#if FP_NOTIFY_TYPE == FPSENSOR_FB_DRM +#include +#define FP_NOTIFY_ON MSM_DRM_BLANK_UNBLANK +#define FP_NOTIFY_OFF MSM_DRM_BLANK_POWERDOWN +#define FP_NOTIFY_EVENT_BLANK MSM_DRM_EARLY_EVENT_BLANK //MSM_DRM_EVENT_BLANK +#define fpsensor_fb_register_client(client) msm_drm_register_client(client); +#define fpsensor_fb_unregister_client(client) msm_drm_unregister_client(client); +#else +#define FP_NOTIFY_ON FB_BLANK_UNBLANK +#define FP_NOTIFY_OFF FB_BLANK_POWERDOWN +#define FP_NOTIFY_EVENT_BLANK FB_EVENT_BLANK +#define fpsensor_fb_register_client(client) fb_register_client(client); +#define fpsensor_fb_unregister_client(client) fb_unregister_client(client) +#endif +#endif + +/* debug log setting */ +static u8 fpsensor_debug_level = INFO_LOG; +/* global variables */ +static fpsensor_data_t *g_fpsensor = NULL; +uint32_t g_cmd_sn = 0; + +#if FPSENSOR_WAKEUP_TYPE == FPSENSOR_WAKEUP_SOURCE +#include +#include +struct wakeup_source g_ttw_wl; +#else +#include +struct wake_lock g_ttw_wl; +#endif + +/* -------------------------------------------------------------------- */ +/* fingerprint chip hardware configuration */ +/* -------------------------------------------------------------------- */ +static void fpsensor_gpio_free(fpsensor_data_t *fpsensor) +{ + struct device *dev = &fpsensor->spi->dev; + + if (fpsensor->irq_gpio != 0 ) { + devm_gpio_free(dev, fpsensor->irq_gpio); + fpsensor->irq_gpio = 0; + } + if (fpsensor->reset_gpio != 0) { + devm_gpio_free(dev, fpsensor->reset_gpio); + fpsensor->reset_gpio = 0; + } +#if FPSENSOR_USE_QCOM_POWER_GPIO + if (fpsensor->power_gpio != 0) { + devm_gpio_free(dev, fpsensor->power_gpio); + fpsensor->power_gpio = 0; + } +#endif +} + +static void fpsensor_irq_gpio_cfg(fpsensor_data_t *fpsensor) +{ + int error = 0; + + error = gpio_direction_input(fpsensor->irq_gpio); + if (error) { + fpsensor_debug(ERR_LOG, "setup fpsensor irq gpio for input failed!error[%d]\n", error); + return ; + } + + fpsensor->irq = gpio_to_irq(fpsensor->irq_gpio); + fpsensor_debug(DEBUG_LOG, "fpsensor irq number[%d]\n", fpsensor->irq); + if (fpsensor->irq <= 0) { + fpsensor_debug(ERR_LOG, "fpsensor irq gpio to irq failed!\n"); + return ; + } + + return; +} + +static int fpsensor_request_named_gpio(fpsensor_data_t *fpsensor_dev, const char *label, int *gpio) +{ + struct device *dev = &fpsensor_dev->spi->dev; + struct device_node *np = dev->of_node; + int ret = of_get_named_gpio(np, label, 0); + + if (ret < 0) { + fpsensor_debug(ERR_LOG, "failed to get '%s'\n", label); + return ret; + } + *gpio = ret; + ret = devm_gpio_request(dev, *gpio, label); + if (ret) { + fpsensor_debug(ERR_LOG, "failed to request gpio %d\n", *gpio); + return ret; + } + + fpsensor_debug(ERR_LOG, "%s %d\n", label, *gpio); + return ret; +} + +/* delay us after reset */ +static void fpsensor_hw_reset(int delay) +{ + FUNC_ENTRY(); + gpio_set_value(g_fpsensor->reset_gpio, 1); + + udelay(100); + gpio_set_value(g_fpsensor->reset_gpio, 0); + + udelay(1000); + gpio_set_value(g_fpsensor->reset_gpio, 1); + + if (delay) { + udelay(delay); + } + + FUNC_EXIT(); + return; +} + +static int fpsensor_get_gpio_dts_info(fpsensor_data_t *fpsensor) +{ + int ret = 0; + + FUNC_ENTRY(); + // get interrupt gpio resource + ret = fpsensor_request_named_gpio(fpsensor, "fp-gpio-int", &fpsensor->irq_gpio); + if (ret) { + fpsensor_debug(ERR_LOG, "Failed to request irq GPIO. ret = %d\n", ret); + return -1; + } + + // get reest gpio resourece + ret = fpsensor_request_named_gpio(fpsensor, "fp-gpio-reset", &fpsensor->reset_gpio); + if (ret) { + fpsensor_debug(ERR_LOG, "Failed to request reset GPIO. ret = %d\n", ret); + return -1; + } +#if FPSENSOR_USE_QCOM_POWER_GPIO + // get power gpio resourece + ret = fpsensor_request_named_gpio(fpsensor, "fp-gpio-power", &fpsensor->power_gpio); + if (ret) { + fpsensor_debug(ERR_LOG, "Failed to request power GPIO. ret = %d\n", ret); + return -1; + } + // set power direction output + gpio_direction_output(fpsensor->power_gpio, 1); + gpio_set_value(fpsensor->power_gpio, 1); +#endif + // set reset direction output + gpio_direction_output(fpsensor->reset_gpio, 1); + fpsensor_hw_reset(1250); + + return ret; +} + +static void setRcvIRQ(int val) +{ + fpsensor_data_t *fpsensor_dev = g_fpsensor; + fpsensor_dev->RcvIRQ = val; +} + +static void fpsensor_enable_irq(fpsensor_data_t *fpsensor_dev) +{ + FUNC_ENTRY(); + setRcvIRQ(0); + /* Request that the interrupt should be wakeable */ + if (fpsensor_dev->irq_enabled == 0) { + enable_irq(fpsensor_dev->irq); + fpsensor_dev->irq_enabled = 1; + } + FUNC_EXIT(); + return; +} + +static void fpsensor_disable_irq(fpsensor_data_t *fpsensor_dev) +{ + FUNC_ENTRY(); + + if (0 == fpsensor_dev->device_available) { + fpsensor_debug(ERR_LOG, "%s, devices not available\n", __func__); + goto out; + } + + if (0 == fpsensor_dev->irq_enabled) { + fpsensor_debug(ERR_LOG, "%s, irq already disabled\n", __func__); + goto out; + } + + if (fpsensor_dev->irq) { + disable_irq_nosync(fpsensor_dev->irq); + fpsensor_debug(DEBUG_LOG, "%s disable interrupt!\n", __func__); + } + fpsensor_dev->irq_enabled = 0; + +out: + setRcvIRQ(0); + FUNC_EXIT(); + return; +} + +static irqreturn_t fpsensor_irq(int irq, void *handle) +{ + fpsensor_data_t *fpsensor_dev = (fpsensor_data_t *)handle; + + /* Make sure 'wakeup_enabled' is updated before using it + ** since this is interrupt context (other thread...) */ + smp_rmb(); +#if FPSENSOR_WAKEUP_TYPE == FPSENSOR_WAKEUP_SOURCE + __pm_wakeup_event(&g_ttw_wl, 1000); +#else + wake_lock_timeout(&g_ttw_wl, msecs_to_jiffies(1000)); +#endif + setRcvIRQ(1); + wake_up_interruptible(&fpsensor_dev->wq_irq_return); + + return IRQ_HANDLED; +} + +// release and cleanup fpsensor char device +static void fpsensor_dev_cleanup(fpsensor_data_t *fpsensor) +{ + FUNC_ENTRY(); + + cdev_del(&fpsensor->cdev); + unregister_chrdev_region(fpsensor->devno, FPSENSOR_NR_DEVS); + device_destroy(fpsensor->class, fpsensor->devno); + class_destroy(fpsensor->class); + + FUNC_EXIT(); +} + +static long fpsensor_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + fpsensor_data_t *fpsensor_dev = NULL; + int retval = 0; + uint32_t val = 0; + int irqf; + + fpsensor_debug(INFO_LOG, "[rickon]: fpsensor ioctl cmd : 0x%x \n", cmd ); + fpsensor_dev = (fpsensor_data_t *)filp->private_data; + fpsensor_dev->cancel = 0 ; + switch (cmd) { + case FPSENSOR_IOC_INIT: + fpsensor_debug(INFO_LOG, "%s: fpsensor init started======\n", __func__); + retval = fpsensor_get_gpio_dts_info(fpsensor_dev); + if (retval) { + break; + } + fpsensor_irq_gpio_cfg(fpsensor_dev); + //regist irq + irqf = IRQF_TRIGGER_RISING | IRQF_ONESHOT; + retval = devm_request_threaded_irq(&g_fpsensor->spi->dev, g_fpsensor->irq, fpsensor_irq, + NULL, irqf, dev_name(&g_fpsensor->spi->dev), g_fpsensor); + if (retval == 0) { + fpsensor_debug(INFO_LOG, " irq thread reqquest success!\n"); + } else { + fpsensor_debug(INFO_LOG, " irq thread request failed , retval =%d \n", retval); + break; + } + enable_irq_wake(g_fpsensor->irq); + fpsensor_dev->device_available = 1; + // fix Unbalanced enable for IRQ, disable irq at first + fpsensor_dev->irq_enabled = 1; + fpsensor_disable_irq(fpsensor_dev); + fpsensor_debug(INFO_LOG, "%s: fpsensor init finished======\n", __func__); + break; + + case FPSENSOR_IOC_EXIT: + fpsensor_disable_irq(fpsensor_dev); + if (fpsensor_dev->irq) { + free_irq(fpsensor_dev->irq, fpsensor_dev); + fpsensor_dev->irq_enabled = 0; + } + fpsensor_dev->device_available = 0; + fpsensor_gpio_free(fpsensor_dev); + fpsensor_debug(INFO_LOG, "%s: fpsensor exit finished======\n", __func__); + break; + + case FPSENSOR_IOC_RESET: + fpsensor_debug(INFO_LOG, "%s: chip reset command\n", __func__); + fpsensor_hw_reset(1250); + break; + + case FPSENSOR_IOC_ENABLE_IRQ: + fpsensor_debug(INFO_LOG, "%s: chip ENable IRQ command\n", __func__); + fpsensor_enable_irq(fpsensor_dev); + break; + + case FPSENSOR_IOC_DISABLE_IRQ: + fpsensor_debug(INFO_LOG, "%s: chip disable IRQ command\n", __func__); + fpsensor_disable_irq(fpsensor_dev); + break; + case FPSENSOR_IOC_GET_INT_VAL: + val = gpio_get_value(fpsensor_dev->irq_gpio); + if (copy_to_user((void __user *)arg, (void *)&val, sizeof(uint32_t))) { + fpsensor_debug(ERR_LOG, "Failed to copy data to user\n"); + retval = -EFAULT; + break; + } + retval = 0; + break; + case FPSENSOR_IOC_ENABLE_SPI_CLK: + fpsensor_debug(INFO_LOG, "%s: ENABLE_SPI_CLK ======\n", __func__); + break; + case FPSENSOR_IOC_DISABLE_SPI_CLK: + fpsensor_debug(INFO_LOG, "%s: DISABLE_SPI_CLK ======\n", __func__); + break; + case FPSENSOR_IOC_ENABLE_POWER: + fpsensor_debug(INFO_LOG, "%s: FPSENSOR_IOC_ENABLE_POWER ======\n", __func__); + break; + case FPSENSOR_IOC_DISABLE_POWER: + fpsensor_debug(INFO_LOG, "%s: FPSENSOR_IOC_DISABLE_POWER ======\n", __func__); + break; + case FPSENSOR_IOC_REMOVE: + fpsensor_disable_irq(fpsensor_dev); + if (fpsensor_dev->irq) { + free_irq(fpsensor_dev->irq, fpsensor_dev); + fpsensor_dev->irq_enabled = 0; + } + fpsensor_dev->device_available = 0; + fpsensor_gpio_free(fpsensor_dev); + fpsensor_dev_cleanup(fpsensor_dev); +#if FP_NOTIFY + fpsensor_fb_unregister_client(&fpsensor_dev->notifier); +#endif + fpsensor_dev->free_flag = 1; + fpsensor_debug(INFO_LOG, "%s remove finished\n", __func__); + break; + case FPSENSOR_IOC_CANCEL_WAIT: + fpsensor_debug(INFO_LOG, "%s: FPSENSOR CANCEL WAIT\n", __func__); + wake_up_interruptible(&fpsensor_dev->wq_irq_return); + fpsensor_dev->cancel = 1; + break; +#if FP_NOTIFY + case FPSENSOR_IOC_GET_FP_STATUS : + val = fpsensor_dev->fb_status; + fpsensor_debug(INFO_LOG, "%s: FPSENSOR_IOC_GET_FP_STATUS %d \n",__func__, fpsensor_dev->fb_status); + if (copy_to_user((void __user *)arg, (void *)&val, sizeof(uint32_t))) { + fpsensor_debug(ERR_LOG, "Failed to copy data to user\n"); + retval = -EFAULT; + break; + } + retval = 0; + break; +#endif + case FPSENSOR_IOC_ENABLE_REPORT_BLANKON: + if (copy_from_user(&val, (void __user *)arg, sizeof(uint32_t))) { + retval = -EFAULT; + break; + } + fpsensor_dev->enable_report_blankon = val; + fpsensor_debug(INFO_LOG, "%s: FPSENSOR_IOC_ENABLE_REPORT_BLANKON: %d\n", __func__, val); + break; + case FPSENSOR_IOC_UPDATE_DRIVER_SN: + if (copy_from_user(&g_cmd_sn, (void __user *)arg, sizeof(uint32_t))) { + fpsensor_debug(ERR_LOG, "Failed to copy g_cmd_sn from user to kernel\n"); + retval = -EFAULT; + break; + } + //fpsensor_debug(INFO_LOG, "%s: FPSENSOR_IOC_UPDATE_DRIVER_SN: %d\n", __func__, g_cmd_sn); + break; + default: + fpsensor_debug(ERR_LOG, "fpsensor doesn't support this command(0x%x)\n", cmd); + break; + } + + //FUNC_EXIT(); + return retval; +} + +static long fpsensor_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return fpsensor_ioctl(filp, cmd, (unsigned long)(arg)); +} + +static unsigned int fpsensor_poll(struct file *filp, struct poll_table_struct *wait) +{ + unsigned int ret = 0; + + ret |= POLLIN; + poll_wait(filp, &g_fpsensor->wq_irq_return, wait); + if (g_fpsensor->cancel == 1) { + fpsensor_debug(ERR_LOG, " cancle\n"); + ret = POLLERR; + g_fpsensor->cancel = 0; + return ret; + } + + if ( g_fpsensor->RcvIRQ) { + if (g_fpsensor->RcvIRQ == 2) { + fpsensor_debug(ERR_LOG, " get fp on notify\n"); + ret |= POLLHUP; + } else { + fpsensor_debug(ERR_LOG, " get irq\n"); + ret |= POLLRDNORM; + } + } else { + ret = 0; + } + return ret; +} + +static int fpsensor_open(struct inode *inode, struct file *filp) +{ + fpsensor_data_t *fpsensor_dev; + + FUNC_ENTRY(); + fpsensor_dev = container_of(inode->i_cdev, fpsensor_data_t, cdev); + fpsensor_dev->users++; + fpsensor_dev->device_available = 1; + filp->private_data = fpsensor_dev; + FUNC_EXIT(); + return 0; +} + +static int fpsensor_release(struct inode *inode, struct file *filp) +{ + fpsensor_data_t *fpsensor_dev; + int status = 0; + + FUNC_ENTRY(); + fpsensor_dev = filp->private_data; + filp->private_data = NULL; + + /*last close??*/ + fpsensor_dev->users--; + if (fpsensor_dev->users <= 0) { + fpsensor_debug(INFO_LOG, "%s, disble_irq. irq = %d\n", __func__, fpsensor_dev->irq); + fpsensor_disable_irq(fpsensor_dev); + } + fpsensor_dev->device_available = 0; + FUNC_EXIT(); + return status; +} + +static ssize_t fpsensor_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + fpsensor_debug(ERR_LOG, "Not support read opertion in TEE version\n"); + return -EFAULT; +} + +static ssize_t fpsensor_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos) +{ + fpsensor_debug(ERR_LOG, "Not support write opertion in TEE version\n"); + return -EFAULT; +} + +static const struct file_operations fpsensor_fops = { + .owner = THIS_MODULE, + .write = fpsensor_write, + .read = fpsensor_read, + .unlocked_ioctl = fpsensor_ioctl, + .compat_ioctl = fpsensor_compat_ioctl, + .open = fpsensor_open, + .release = fpsensor_release, + .poll = fpsensor_poll, + +}; + +// create and register a char device for fpsensor +static int fpsensor_dev_setup(fpsensor_data_t *fpsensor) +{ + int ret = 0; + dev_t dev_no = 0; + struct device *dev = NULL; + int fpsensor_dev_major = FPSENSOR_DEV_MAJOR; + int fpsensor_dev_minor = 0; + + FUNC_ENTRY(); + + if (fpsensor_dev_major) { + dev_no = MKDEV(fpsensor_dev_major, fpsensor_dev_minor); + ret = register_chrdev_region(dev_no, FPSENSOR_NR_DEVS, FPSENSOR_DEV_NAME); + } else { + ret = alloc_chrdev_region(&dev_no, fpsensor_dev_minor, FPSENSOR_NR_DEVS, FPSENSOR_DEV_NAME); + fpsensor_dev_major = MAJOR(dev_no); + fpsensor_dev_minor = MINOR(dev_no); + fpsensor_debug(INFO_LOG, "fpsensor device major is %d, minor is %d\n", + fpsensor_dev_major, fpsensor_dev_minor); + } + + if (ret < 0) { + fpsensor_debug(ERR_LOG, "can not get device major number %d\n", fpsensor_dev_major); + goto out; + } + + cdev_init(&fpsensor->cdev, &fpsensor_fops); + fpsensor->cdev.owner = THIS_MODULE; + fpsensor->cdev.ops = &fpsensor_fops; + fpsensor->devno = dev_no; + ret = cdev_add(&fpsensor->cdev, dev_no, FPSENSOR_NR_DEVS); + if (ret) { + fpsensor_debug(ERR_LOG, "add char dev for fpsensor failed\n"); + goto release_region; + } + + fpsensor->class = class_create(THIS_MODULE, FPSENSOR_CLASS_NAME); + if (IS_ERR(fpsensor->class)) { + fpsensor_debug(ERR_LOG, "create fpsensor class failed\n"); + ret = PTR_ERR(fpsensor->class); + goto release_cdev; + } + + dev = device_create(fpsensor->class, &fpsensor->spi->dev, dev_no, fpsensor, FPSENSOR_DEV_NAME); + if (IS_ERR(dev)) { + fpsensor_debug(ERR_LOG, "create device for fpsensor failed\n"); + ret = PTR_ERR(dev); + goto release_class; + } + FUNC_EXIT(); + return ret; + +release_class: + class_destroy(fpsensor->class); + fpsensor->class = NULL; +release_cdev: + cdev_del(&fpsensor->cdev); +release_region: + unregister_chrdev_region(dev_no, FPSENSOR_NR_DEVS); +out: + FUNC_EXIT(); + return ret; +} + +#if FP_NOTIFY +static int fpsensor_fb_notifier_callback(struct notifier_block* self, unsigned long event, void* data) +{ + int retval = 0; + static char screen_status[64] = { '\0' }; + struct fb_event* evdata = data; + unsigned int blank; + fpsensor_data_t *fpsensor_dev = g_fpsensor; + + fpsensor_debug(INFO_LOG,"%s enter, event: 0x%x\n", __func__, (unsigned)event); + if (event != FP_NOTIFY_EVENT_BLANK) { + return 0; + } + + blank = *(int*)evdata->data; + fpsensor_debug(INFO_LOG,"%s enter, blank=0x%x\n", __func__, blank); + + switch (blank) { + case FP_NOTIFY_ON: + fpsensor_debug(INFO_LOG,"%s: lcd on notify\n", __func__); + sprintf(screen_status, "SCREEN_STATUS=%s", "ON"); + fpsensor_dev->fb_status = 1; + if( fpsensor_dev->enable_report_blankon) { + fpsensor_dev->RcvIRQ = 2; + wake_up_interruptible(&fpsensor_dev->wq_irq_return); + } + break; + + case FP_NOTIFY_OFF: + fpsensor_debug(INFO_LOG,"%s: lcd off notify\n", __func__); + sprintf(screen_status, "SCREEN_STATUS=%s", "OFF"); + fpsensor_dev->fb_status = 0; + break; + + default: + fpsensor_debug(INFO_LOG,"%s: other notifier, ignore\n", __func__); + break; + } + + fpsensor_debug(INFO_LOG,"%s %s leave.\n", screen_status, __func__); + return retval; +} +#endif + +static int fpsensor_probe(struct platform_device *pdev) +{ + int status = 0; + fpsensor_data_t *fpsensor_dev = NULL; + + FUNC_ENTRY(); + + /* Allocate driver data */ + fpsensor_dev = kzalloc(sizeof(*fpsensor_dev), GFP_KERNEL); + if (!fpsensor_dev) { + status = -ENOMEM; + fpsensor_debug(ERR_LOG, "%s, Failed to alloc memory for fpsensor device.\n", __func__); + goto out; + } + + /* Initialize the driver data */ + g_fpsensor = fpsensor_dev; + fpsensor_dev->spi = pdev ; + fpsensor_dev->device_available = 0; + fpsensor_dev->users = 0; + fpsensor_dev->irq = 0; + fpsensor_dev->power_gpio = 0; + fpsensor_dev->reset_gpio = 0; + fpsensor_dev->irq_gpio = 0; + fpsensor_dev->irq_enabled = 0; + fpsensor_dev->free_flag = 0; + fpsensor_dev->fb_status = 1; + /* setup a char device for fpsensor */ + status = fpsensor_dev_setup(fpsensor_dev); + if (status) { + fpsensor_debug(ERR_LOG, "fpsensor setup char device failed, %d", status); + goto release_drv_data; + } + init_waitqueue_head(&fpsensor_dev->wq_irq_return); +#if FPSENSOR_WAKEUP_TYPE == FPSENSOR_WAKEUP_SOURCE + wakeup_source_init(&g_ttw_wl, "fpsensor_ttw_wl"); +#else + wake_lock_init(&g_ttw_wl, WAKE_LOCK_SUSPEND, "fpsensor_ttw_wl"); +#endif + fpsensor_dev->device_available = 1; +#if FP_NOTIFY + fpsensor_dev->notifier.notifier_call = fpsensor_fb_notifier_callback; + fpsensor_fb_register_client(&fpsensor_dev->notifier); +#endif + + fpsensor_debug(INFO_LOG, "%s finished, driver version: %s\n", __func__, FPSENSOR_SPI_VERSION); + goto out; + +release_drv_data: + kfree(fpsensor_dev); + fpsensor_dev = NULL; +out: + FUNC_EXIT(); + return status; +} + +static int fpsensor_remove(struct platform_device *pdev) +{ + fpsensor_data_t *fpsensor_dev = g_fpsensor; + + FUNC_ENTRY(); + fpsensor_disable_irq(fpsensor_dev); + if (fpsensor_dev->irq) + free_irq(fpsensor_dev->irq, fpsensor_dev); + +#if FP_NOTIFY + fpsensor_fb_unregister_client(&fpsensor_dev->notifier); +#endif + fpsensor_gpio_free(fpsensor_dev); + fpsensor_dev_cleanup(fpsensor_dev); +#if FPSENSOR_WAKEUP_TYPE == FPSENSOR_WAKEUP_SOURCE + wakeup_source_trash(&g_ttw_wl); +#else + wake_lock_destroy(&g_ttw_wl); +#endif + kfree(fpsensor_dev); + g_fpsensor = NULL; + + FUNC_EXIT(); + return 0; +} + +static int fpsensor_suspend(struct platform_device *pdev, pm_message_t state) +{ + return 0; +} + +static int fpsensor_resume( struct platform_device *pdev) +{ + return 0; +} + +#ifdef CONFIG_OF +static struct of_device_id fpsensor_of_match[] = { + { .compatible = "qcom,fingerprint-gpio" }, + {} +}; +//MODULE_DEVICE_TABLE(of, fpsensor_of_match); +#endif + +static struct platform_driver fpsensor_driver = { + .driver = { + .name = FPSENSOR_DEV_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = fpsensor_of_match, +#endif + }, + .probe = fpsensor_probe, + .remove = fpsensor_remove, + .suspend = fpsensor_suspend, + .resume = fpsensor_resume, +}; + +static int __init fpsensor_init(void) +{ + int status; + + status = platform_driver_register(&fpsensor_driver); + if (status < 0) { + fpsensor_debug(ERR_LOG, "%s, Failed to register SPI driver.\n", __func__); + } + + return status; +} +module_init(fpsensor_init); + +static void __exit fpsensor_exit(void) +{ + platform_driver_unregister(&fpsensor_driver); +} +module_exit(fpsensor_exit); + +MODULE_AUTHOR("xhli"); +MODULE_DESCRIPTION(" Fingerprint chip TEE driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:fpsensor-drivers"); diff --git a/drivers/input/misc/chipone_fps_mmi/fpsensor_spi_tee.h b/drivers/input/misc/chipone_fps_mmi/fpsensor_spi_tee.h new file mode 100644 index 000000000000..d221490073e2 --- /dev/null +++ b/drivers/input/misc/chipone_fps_mmi/fpsensor_spi_tee.h @@ -0,0 +1,69 @@ +#ifndef __FPSENSOR_SPI_TEE_H +#define __FPSENSOR_SPI_TEE_H + +#include +#include +#include +#include +#include + +#define FPSENSOR_DEV_NAME "fpsensor" +#define FPSENSOR_CLASS_NAME "fpsensor" +#define FPSENSOR_DEV_MAJOR 0 +#define N_SPI_MINORS 32 /* ... up to 256 */ +#define FPSENSOR_NR_DEVS 1 + +#define ERR_LOG (0) +#define INFO_LOG (1) +#define DEBUG_LOG (2) +#define fpsensor_debug(level, fmt, args...) do { \ + if (fpsensor_debug_level >= level) {\ + printk("[fpCoreDriver][SN=%d] " fmt, g_cmd_sn, ##args); \ + } \ + } while (0) +#define FUNC_ENTRY() fpsensor_debug(DEBUG_LOG, "%s, %d, entry\n", __func__, __LINE__) +#define FUNC_EXIT() fpsensor_debug(DEBUG_LOG, "%s, %d, exit\n", __func__, __LINE__) + +/**********************IO Magic**********************/ +#define FPSENSOR_IOC_MAGIC 0xf0 //CHIP + +/* define commands */ +#define FPSENSOR_IOC_INIT _IOWR(FPSENSOR_IOC_MAGIC,0,uint32_t) +#define FPSENSOR_IOC_EXIT _IOWR(FPSENSOR_IOC_MAGIC,1,uint32_t) +#define FPSENSOR_IOC_RESET _IOWR(FPSENSOR_IOC_MAGIC,2,uint32_t) +#define FPSENSOR_IOC_ENABLE_IRQ _IOWR(FPSENSOR_IOC_MAGIC,3,uint32_t) +#define FPSENSOR_IOC_DISABLE_IRQ _IOWR(FPSENSOR_IOC_MAGIC,4,uint32_t) +#define FPSENSOR_IOC_GET_INT_VAL _IOWR(FPSENSOR_IOC_MAGIC,5,uint32_t) +#define FPSENSOR_IOC_DISABLE_SPI_CLK _IOWR(FPSENSOR_IOC_MAGIC,6,uint32_t) +#define FPSENSOR_IOC_ENABLE_SPI_CLK _IOWR(FPSENSOR_IOC_MAGIC,7,uint32_t) +#define FPSENSOR_IOC_ENABLE_POWER _IOWR(FPSENSOR_IOC_MAGIC,8,uint32_t) +#define FPSENSOR_IOC_DISABLE_POWER _IOWR(FPSENSOR_IOC_MAGIC,9,uint32_t) +/* fp sensor has change to sleep mode while screen off */ +#define FPSENSOR_IOC_ENTER_SLEEP_MODE _IOWR(FPSENSOR_IOC_MAGIC,11,uint32_t) +#define FPSENSOR_IOC_REMOVE _IOWR(FPSENSOR_IOC_MAGIC,12,uint32_t) +#define FPSENSOR_IOC_CANCEL_WAIT _IOWR(FPSENSOR_IOC_MAGIC,13,uint32_t) +#define FPSENSOR_IOC_GET_FP_STATUS _IOWR(FPSENSOR_IOC_MAGIC,19,uint32_t) +#define FPSENSOR_IOC_ENABLE_REPORT_BLANKON _IOWR(FPSENSOR_IOC_MAGIC,21,uint32_t) +#define FPSENSOR_IOC_UPDATE_DRIVER_SN _IOWR(FPSENSOR_IOC_MAGIC,22,uint32_t) +typedef struct { + dev_t devno; + struct class *class; + struct cdev cdev; + struct platform_device *spi; + unsigned int users; + u8 device_available; /* changed during fingerprint chip sleep and wakeup phase */ + u8 irq_enabled; + volatile unsigned int RcvIRQ; + int irq; + int irq_gpio; + int reset_gpio; + int power_gpio; + wait_queue_head_t wq_irq_return; + int cancel; + struct notifier_block notifier; + u8 fb_status; + int enable_report_blankon; + int free_flag; +} fpsensor_data_t; + +#endif /* __FPSENSOR_SPI_TEE_H */ diff --git a/drivers/input/misc/chipone_fps_mmi/fpsensor_wakelock.h b/drivers/input/misc/chipone_fps_mmi/fpsensor_wakelock.h new file mode 100644 index 000000000000..bda854f5bf2b --- /dev/null +++ b/drivers/input/misc/chipone_fps_mmi/fpsensor_wakelock.h @@ -0,0 +1,68 @@ +/* include/linux/wakelock.h + * + * Copyright (C) 2007-2012 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef _BF_FP_WAKELOCK_H +#define _BF_FP_WAKELOCK_H + +#include +#include + +/* A wake_lock prevents the system from entering suspend or other low power + * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock + * prevents a full system suspend. + */ + +enum { + WAKE_LOCK_SUSPEND, /* Prevent suspend */ + WAKE_LOCK_TYPE_COUNT +}; + +struct wake_lock { + struct wakeup_source ws; +}; + +static inline void wake_lock_init(struct wake_lock *lock, int type, + const char *name) +{ + wakeup_source_init(&lock->ws, name); +} + +static inline void wake_lock_destroy(struct wake_lock *lock) +{ + wakeup_source_trash(&lock->ws); +} + +static inline void wake_lock(struct wake_lock *lock) +{ + __pm_stay_awake(&lock->ws); +} + +static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) +{ + __pm_wakeup_event(&lock->ws, jiffies_to_msecs(timeout)); +} + +static inline void wake_unlock(struct wake_lock *lock) +{ + __pm_relax(&lock->ws); +} + +static inline int wake_lock_active(struct wake_lock *lock) +{ + return lock->ws.active; +} + +#endif +