summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/fpsensor/build.mk4
-rw-r--r--common/fpsensor/fpsensor_stubs.c30
-rw-r--r--driver/build.mk6
-rw-r--r--driver/fingerprint/build.mk10
-rw-r--r--driver/fingerprint/fpc/bep/build.mk23
-rw-r--r--driver/fingerprint/fpc/bep/fpc1025_private.h52
-rw-r--r--driver/fingerprint/fpc/bep/fpc1035_private.h52
-rw-r--r--driver/fingerprint/fpc/bep/fpc_bio_algorithm.h136
-rw-r--r--driver/fingerprint/fpc/bep/fpc_misc.c51
-rw-r--r--driver/fingerprint/fpc/bep/fpc_private.c260
-rw-r--r--driver/fingerprint/fpc/bep/fpc_sensor_spi.c94
-rw-r--r--driver/fingerprint/fpc/bep/fpc_sensor_spi.h98
-rw-r--r--driver/fingerprint/fpc/bep/fpc_timebase.c29
-rw-r--r--driver/fingerprint/fpc/bep/fpc_timebase.h48
-rw-r--r--driver/fingerprint/fpc/build.mk16
-rw-r--r--driver/fingerprint/fpc/libfp/build.mk21
-rw-r--r--driver/fingerprint/fpc/libfp/fpc1145_private.h42
-rw-r--r--driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h265
-rw-r--r--driver/fingerprint/fpc/libfp/fpc_private.c317
-rw-r--r--driver/fingerprint/fpc/libfp/fpc_private.h104
-rw-r--r--driver/fingerprint/fpc/libfp/fpc_sensor_pal.c60
-rw-r--r--driver/fingerprint/fpc/libfp/fpc_sensor_pal.h118
22 files changed, 1802 insertions, 34 deletions
diff --git a/common/fpsensor/build.mk b/common/fpsensor/build.mk
index 03bc80f2ef..a1eeaa9932 100644
--- a/common/fpsensor/build.mk
+++ b/common/fpsensor/build.mk
@@ -10,7 +10,3 @@ _fpsensor_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)fpsensor_state.o
all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)fpsensor_crypto.o
all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)fpsensor.o
-
-ifeq ($(HAS_MOCK_FP_SENSOR),)
-all-obj-$(HAS_TASK_FPSENSOR)+=$(_fpsensor_dir)fpsensor_stubs.o
-endif
diff --git a/common/fpsensor/fpsensor_stubs.c b/common/fpsensor/fpsensor_stubs.c
deleted file mode 100644
index 3acaa689f5..0000000000
--- a/common/fpsensor/fpsensor_stubs.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright 2019 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "common.h"
-#include "fpsensor_state.h"
-#include "panic.h"
-
-/*
- * These are built when we don't have the private driver files.
- * The definitions are intentionally kept separate from the mock
- * implementations so that we don't accidentally compile mocks into a release.
- */
-
-#if !defined(HAVE_FP_PRIVATE_DRIVER)
-
-int fp_sensor_init(void)
-{
- panic("fp_sensor_init stub should never be called\n");
- return EC_ERROR_UNKNOWN;
-}
-
-int fp_sensor_deinit(void)
-{
- panic("fp_sensor_deinit stub should never be called\n");
- return EC_ERROR_UNKNOWN;
-}
-
-#endif /* !HAVE_FP_PRIVATE_DRIVER */
diff --git a/driver/build.mk b/driver/build.mk
index aa962fca95..4a22432ded 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -6,6 +6,9 @@
# Drivers for off-chip devices
#
+# Note that this variable includes the trailing "/"
+_driver_cur_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
+
# Accelerometers
driver-$(CONFIG_ACCEL_BMA255)+=accel_bma2x2.o
driver-$(CONFIG_ACCEL_KXCJ9)+=accel_kionix.o
@@ -72,6 +75,9 @@ driver-$(CONFIG_CHARGER_RT9466)+=charger/rt946x.o
driver-$(CONFIG_CHARGER_RT9467)+=charger/rt946x.o
driver-$(CONFIG_CHARGER_SY21612)+=charger/sy21612.o
+# Fingerprint Sensors
+include $(_driver_cur_dir)fingerprint/build.mk
+
# I/O expander
driver-$(CONFIG_IO_EXPANDER_PCA9534)+=ioexpander_pca9534.o
driver-$(CONFIG_IO_EXPANDER_NCT38XX)+=ioexpander_nct38xx.o
diff --git a/driver/fingerprint/build.mk b/driver/fingerprint/build.mk
new file mode 100644
index 0000000000..862fa29914
--- /dev/null
+++ b/driver/fingerprint/build.mk
@@ -0,0 +1,10 @@
+# Copyright 2019 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Build fingerprint drivers
+
+# Note that this variable includes the trailing "/"
+_fingerprint_cur_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
+
+include $(_fingerprint_cur_dir)fpc/build.mk
diff --git a/driver/fingerprint/fpc/bep/build.mk b/driver/fingerprint/fpc/bep/build.mk
new file mode 100644
index 0000000000..fc704e172a
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/build.mk
@@ -0,0 +1,23 @@
+# Copyright 2019 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# FPC BEP source files build
+
+# Note that this variable includes the trailing "/"
+_bep_cur_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
+
+# Make sure output directory is created (in build directory)
+dirs-y+="$(_bep_cur_dir)"
+
+sensor-$(CONFIG_FP_SENSOR_FPC1025)=fpc1025
+sensor-$(CONFIG_FP_SENSOR_FPC1035)=fpc1035
+
+# Only build for these objects for the RW image
+all-obj-rw+=$(_bep_cur_dir)fpc_misc.o \
+ $(_bep_cur_dir)fpc_private.o \
+ $(_bep_cur_dir)fpc_sensor_spi.o \
+ $(_bep_cur_dir)fpc_timebase.o
+fp_sensor_header-rw=$(_bep_cur_dir)$(sensor-rw)_private.h
+
+CPPFLAGS+=-DFP_SENSOR_PRIVATE=$(fp_sensor_header-rw)
diff --git a/driver/fingerprint/fpc/bep/fpc1025_private.h b/driver/fingerprint/fpc/bep/fpc1025_private.h
new file mode 100644
index 0000000000..eddb435d4a
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/fpc1025_private.h
@@ -0,0 +1,52 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_FPC1025_PRIVATE_H
+#define __CROS_EC_FPC1025_PRIVATE_H
+
+/* Define sensor type */
+#define FP_SENSOR_CONFIG_FPC1025
+
+/* The 16-bit hardware ID is 0x021y */
+#define FP_SENSOR_HWID 0x021
+
+/* Sensor type name */
+#define FP_SENSOR_NAME "FPC1025"
+
+/* Sensor pixel resolution */
+#define FP_SENSOR_RES_X (160) /**< Sensor width */
+#define FP_SENSOR_RES_Y (160) /**< Sensor height */
+#define FP_SENSOR_RES_BPP (8) /**< Resolution bits per pixel */
+
+/*
+ * Sensor image size
+ *
+ * Value from fpc_bep_image_get_buffer_size(): (160*160)+660
+ */
+#define FP_SENSOR_IMAGE_SIZE (26260)
+#define FP_SENSOR_REAL_IMAGE_SIZE (FP_SENSOR_RES_X * FP_SENSOR_RES_Y)
+/* Offset of image data in fp_buffer */
+#define FP_SENSOR_IMAGE_OFFSET (400)
+
+/*
+ * Constant value for the enrollment data size
+ *
+ * Size of private fp_bio_enrollment_t
+ */
+#define FP_ALGORITHM_ENROLLMENT_SIZE (4)
+
+/*
+ * Constant value corresponding to the maximum template size
+ * for FPC1025 sensor. Client template memory allocation must
+ * have this size. This includes extra memory for template update.
+ *
+ * Template size + alignment padding + size of template size variable
+ */
+#define FP_ALGORITHM_TEMPLATE_SIZE (5088 + 0 + 4)
+
+/* Max number of templates stored / matched against */
+#define FP_MAX_FINGER_COUNT (5)
+
+#endif /* __CROS_EC_FPC1025_PRIVATE_H */
diff --git a/driver/fingerprint/fpc/bep/fpc1035_private.h b/driver/fingerprint/fpc/bep/fpc1035_private.h
new file mode 100644
index 0000000000..61c423c6b8
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/fpc1035_private.h
@@ -0,0 +1,52 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_FPC1035_PRIVATE_H
+#define __CROS_EC_FPC1035_PRIVATE_H
+
+/* Define sensor type */
+#define FP_SENSOR_CONFIG_FPC1035
+
+/* The 16-bit hardware ID is 0x011y */
+#define FP_SENSOR_HWID 0x011
+
+/* Sensor type name */
+#define FP_SENSOR_NAME "FPC1035"
+
+/* Sensor pixel resolution */
+#define FP_SENSOR_RES_X (112) /**< Sensor width */
+#define FP_SENSOR_RES_Y (88) /**< Sensor height */
+#define FP_SENSOR_RES_BPP (8) /**< Resolution bits per pixel */
+
+/*
+ * Sensor image size
+ *
+ * Value from fpc_bep_image_get_buffer_size(): (112*88)+660
+ */
+#define FP_SENSOR_IMAGE_SIZE (10516)
+#define FP_SENSOR_REAL_IMAGE_SIZE (FP_SENSOR_RES_X * FP_SENSOR_RES_Y)
+/* Offset of image data in fp_buffer */
+#define FP_SENSOR_IMAGE_OFFSET (400)
+
+/*
+ * Constant value for the enrollment data size
+ *
+ * Size of private fp_bio_enrollment_t
+ */
+#define FP_ALGORITHM_ENROLLMENT_SIZE (4)
+
+/*
+ * Constant value corresponding to the maximum template size
+ * for FPC1035 sensor. Client template memory allocation must
+ * have this size. This includes extra memory for template update.
+ *
+ * Template size + alignment padding + size of template size variable
+ */
+#define FP_ALGORITHM_TEMPLATE_SIZE (14373 + 3 + 4)
+
+/* Max number of templates stored / matched against */
+#define FP_MAX_FINGER_COUNT (5)
+
+#endif /* __CROS_EC_FPC1035_PRIVATE_H */
diff --git a/driver/fingerprint/fpc/bep/fpc_bio_algorithm.h b/driver/fingerprint/fpc/bep/fpc_bio_algorithm.h
new file mode 100644
index 0000000000..1bf598a3ee
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/fpc_bio_algorithm.h
@@ -0,0 +1,136 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_FPC_BIO_ALGORITHM_H
+#define __CROS_EC_FPC_BIO_ALGORITHM_H
+
+#include <stdint.h>
+
+/*
+ * An opaque pointer representing an image (scan).
+ */
+typedef void *bio_image_t;
+/*
+ * An opaque pointer representing/uniquely identifying an (serialized) enrolled
+ * template.
+ */
+typedef void *bio_template_t;
+/*
+ * An opaque pointer representing/uniquely identifying enrollment attempt.
+ */
+typedef void *bio_enrollment_t;
+/*
+ * An opaque struct representing algorithm.
+ */
+typedef struct fpc_bep_algorithm fpc_bep_algorithm_t;
+/*
+ * Struct with biometric algorithm information.
+ */
+typedef struct {
+ const fpc_bep_algorithm_t *algorithm;
+ uint32_t template_size;
+} fpc_bio_info_t;
+/*
+ * Initializes biometric algorithm library. Should be the very first function
+ * to be invoked by the biometric daemon.
+ *
+ * Returns 0 on success, negative error code (such as -ENOMEM) on failure.
+ */
+int bio_algorithm_init(void);
+/*
+ * Instructs the biometric library to release all resources in preparation
+ * for the process termination (or unloading the library). Regardless of
+ * the returned error code the action is considered unrecoverable.
+ *
+ * Returns 0 on success, negative error code (such as -ENOMEM) on failure.
+ */
+int bio_algorithm_exit(void);
+/*
+ * Compares given biometric image against a list of enrolled template(s).
+ * In case the image match a template the match_index will indicate which
+ * template in the list that matched.
+ * The algorithm library can update templates with additional biometric data
+ * from the image, if it chooses to do so. The updated template(s) will be
+ * indicated by the out parameter 'updated_templates', a bit-field where
+ * updated template(s) indicated by the corresponding bit being set
+ * Returns:
+ * - negative value on error
+ * - BIO_TEMPLATE_NO_MATCH on non-match
+ * - BIO_TEMPLATE_MATCH for match when template was not updated with new data
+ * - BIO_TEMPLATE_MATCH_UPDATED for match when template was updated
+ * - BIO_TEMPLATE_MATCH_UPDATE_FAILED match, but update failed (do not save)
+ * - BIO_TEMPLATE_LOW_QUALITY when matching could not be performed due to low
+ * image quality
+ * - BIO_TEMPLATE_LOW_COVERAGE when matching could not be performed due to
+ * finger covering too little area of the sensor
+ */
+#define BIO_TEMPLATE_NO_MATCH 0
+#define BIO_TEMPLATE_MATCH 1
+#define BIO_TEMPLATE_MATCH_UPDATED 3
+#define BIO_TEMPLATE_MATCH_UPDATE_FAILED 5
+#define BIO_TEMPLATE_LOW_QUALITY 2
+#define BIO_TEMPLATE_LOW_COVERAGE 4
+
+int bio_template_image_match_list(bio_template_t templ, uint32_t num_templ,
+ bio_image_t image, int32_t *match_index,
+ uint32_t *updated_templ);
+/*
+ * Initiates biometric data enrollment process. Algorithm library returns
+ * 'enrollment handle' that is used for all subsequent enrollment operations.
+ *
+ * Returns 0 on success, negative error code (such as -ENOMEM) on failure.
+ */
+int bio_enrollment_begin(bio_enrollment_t *enrollment);
+/*
+ * Adds fingerprint image to an enrollment.
+ *
+ * The library should expect to copy any relevant data from the “image”
+ * as it is likely to be destroyed (via bio_image_destroy() call) shortly after
+ * this call completes.
+ *
+ * Returns:
+ * - negative value on error
+ * - BIO_ENROLLMENT_OK when image was successfully enrolled
+ * - BIO_ENROLLMENT_LOW_QUALITY when image could not be used due to low
+ * image quality
+ * - BIO_ENROLLMENT_IMMOBILE when image added, but user should be advised
+ * to move finger
+ * - BIO_ENROLLMENT_LOW_COVERAGE when image could not be used due to
+ * finger covering too little area of the sensor
+ * - BIO_ENROLLMENT_INTERNAL_ERROR when an internal error occurred
+ */
+#define BIO_ENROLLMENT_OK 0
+#define BIO_ENROLLMENT_LOW_QUALITY 1
+#define BIO_ENROLLMENT_IMMOBILE 2
+#define BIO_ENROLLMENT_LOW_COVERAGE 3
+#define BIO_ENROLLMENT_INTERNAL_ERROR 5
+
+/* Can be used to detect if image was usable for enrollment or not. */
+#define BIO_ENROLLMENT_PROBLEM_MASK 1
+int bio_enrollment_add_image(bio_enrollment_t enrollment, bio_image_t image);
+/*
+ * Returns percent of coverage accumulated during enrollment process.
+ * Optional method. Regardless of value returned by this call user should call
+ * bio_enrollment_is_complete() to check if algorithm library accumulated enough
+ * data to create a template.
+ *
+ * Returns value in the range 0..100, or negative error (such as -EINVAL);
+ */
+int bio_enrollment_get_percent_complete(bio_enrollment_t enrollment);
+/*
+ * Indicates that given enrollment process is complete, and algorithm library
+ * should generate an active template that can be used in subsequent calls
+ * to bio_image_match() and bio_template_serialize() from enrollment data.
+ * After the template is created the library should release all resources
+ * associated with this enrollment.
+ *
+ * Argument 'templ' is optional and can be set to NULL if caller wishes to
+ * abort enrollment process.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_enrollment_finish(bio_enrollment_t enrollment, bio_template_t *templ);
+
+#endif /* __CROS_EC_FPC_BIO_ALGORITHM_H */
diff --git a/driver/fingerprint/fpc/bep/fpc_misc.c b/driver/fingerprint/fpc/bep/fpc_misc.c
new file mode 100644
index 0000000000..c4c779b702
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/fpc_misc.c
@@ -0,0 +1,51 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* FPC Platform Abstraction Layer */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "shared_mem.h"
+#include "uart.h"
+
+void __unused *fpc_malloc(uint32_t size)
+{
+ char *data;
+ int rc;
+
+ rc = shared_mem_acquire(size, (char **)&data);
+
+ if (rc == 0)
+ return data;
+ else
+ return NULL;
+}
+
+void __unused fpc_free(void *data)
+{
+ shared_mem_release(data);
+}
+
+/* Not in release */
+void __unused fpc_assert_fail(const char *file, uint32_t line, const char *func,
+ const char *expr)
+{
+}
+
+void __unused fpc_log_var(const char *source, uint8_t level, const char *format,
+ ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ uart_vprintf(format, args);
+ va_end(args);
+}
+
+uint32_t abs(int32_t a)
+{
+ return (a < 0) ? (uint32_t)(-a) : (uint32_t)a;
+}
diff --git a/driver/fingerprint/fpc/bep/fpc_private.c b/driver/fingerprint/fpc/bep/fpc_private.c
new file mode 100644
index 0000000000..f69cffb0ce
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/fpc_private.c
@@ -0,0 +1,260 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "fpc_bio_algorithm.h"
+#include "fpsensor.h"
+#include "spi.h"
+#include "system.h"
+#include "util.h"
+
+#include STRINGIFY(FP_SENSOR_PRIVATE)
+
+/* Console output macros */
+#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_FP, format, ## args)
+
+static uint8_t enroll_ctx[FP_ALGORITHM_ENROLLMENT_SIZE] = {0};
+
+/* Recorded error flags */
+static uint16_t errors;
+
+/* FPC specific initialization and de-initialization functions */
+int fp_sensor_open(void);
+int fp_sensor_close(void);
+
+/* Get FPC library version code.*/
+const char *fp_sensor_get_version(void);
+
+/* Get FPC library build info.*/
+const char *fp_sensor_get_build_info(void);
+
+/* Sensor description */
+static struct ec_response_fp_info ec_fp_sensor_info = {
+ /* Sensor identification */
+ .vendor_id = FOURCC('F', 'P', 'C', ' '),
+ .product_id = 9,
+ .model_id = 1,
+ .version = 1,
+ /* Image frame characteristics */
+ .frame_size = FP_SENSOR_IMAGE_SIZE,
+ .pixel_format = V4L2_PIX_FMT_GREY,
+ .width = FP_SENSOR_RES_X,
+ .height = FP_SENSOR_RES_Y,
+ .bpp = FP_SENSOR_RES_BPP,
+};
+
+typedef struct fpc_bep_sensor fpc_bep_sensor_t;
+
+typedef struct {
+ const fpc_bep_sensor_t *sensor;
+ uint32_t image_buffer_size;
+} fpc_sensor_info_t;
+
+#if defined(FP_SENSOR_CONFIG_FPC1025)
+
+extern const fpc_bep_sensor_t fpc_bep_sensor_1025;
+extern const fpc_bep_algorithm_t fpc_bep_algorithm_pfe_1025;
+
+const fpc_sensor_info_t fpc_sensor_info = {
+ .sensor = &fpc_bep_sensor_1025,
+ .image_buffer_size = FP_SENSOR_IMAGE_SIZE,
+};
+
+const fpc_bio_info_t fpc_bio_info = {
+ .algorithm = &fpc_bep_algorithm_pfe_1025,
+ .template_size = FP_ALGORITHM_TEMPLATE_SIZE,
+};
+
+#elif defined(FP_SENSOR_CONFIG_FPC1035)
+
+extern const fpc_bep_sensor_t fpc_bep_sensor_1035;
+extern const fpc_bep_algorithm_t fpc_bep_algorithm_pfe_1035;
+
+const fpc_sensor_info_t fpc_sensor_info = {
+ .sensor = &fpc_bep_sensor_1035,
+ .image_buffer_size = FP_SENSOR_IMAGE_SIZE,
+};
+
+const fpc_bio_info_t fpc_bio_info = {
+ .algorithm = &fpc_bep_algorithm_pfe_1035,
+ .template_size = FP_ALGORITHM_TEMPLATE_SIZE,
+};
+#else
+#error "Sensor type not defined!"
+#endif
+
+/* Sensor IC commands */
+enum fpc_cmd {
+ FPC_CMD_DEEPSLEEP = 0x2C,
+ FPC_CMD_HW_ID = 0xFC,
+};
+
+/* Maximum size of a sensor command SPI transfer */
+#define MAX_CMD_SPI_TRANSFER_SIZE 3
+
+/* Memory for the SPI transfer buffer */
+static uint8_t spi_buf[MAX_CMD_SPI_TRANSFER_SIZE];
+
+static int fpc_send_cmd(const uint8_t cmd)
+{
+ spi_buf[0] = cmd;
+
+ return spi_transaction(SPI_FP_DEVICE, spi_buf, 1, spi_buf,
+ SPI_READBACK_ALL);
+}
+
+void fp_sensor_low_power(void)
+{
+ fpc_send_cmd(FPC_CMD_DEEPSLEEP);
+}
+
+static int fpc_check_hwid(void)
+{
+ uint16_t id;
+ int rc;
+
+ spi_buf[0] = FPC_CMD_HW_ID;
+
+ rc = spi_transaction(SPI_FP_DEVICE, spi_buf, 3, spi_buf,
+ SPI_READBACK_ALL);
+ if (rc) {
+ CPRINTS("FPC HW ID read failed %d", rc);
+ return FP_ERROR_SPI_COMM;
+ }
+
+ id = (spi_buf[1] << 8) | spi_buf[2];
+ if ((id >> 4) != FP_SENSOR_HWID) {
+ CPRINTS("FPC unknown silicon 0x%04x", id);
+ return FP_ERROR_BAD_HWID;
+ }
+ CPRINTS(FP_SENSOR_NAME " id 0x%04x", id);
+
+ return EC_SUCCESS;
+}
+
+/* Reset and initialize the sensor IC */
+int fp_sensor_init(void)
+{
+ int rc;
+
+ /* Print the binary libfpbep.a library version */
+ CPRINTS("FPC libfpbep.a %s", fp_sensor_get_version());
+
+ /* Print the BEP version and build time of the library */
+ CPRINTS("Build information - %s", fp_sensor_get_build_info());
+
+ rc = fp_sensor_open();
+ if (rc) {
+ errors |= FP_ERROR_INIT_FAIL;
+ CPRINTS("Error: fp_sensor_open() failed, result=%d", rc);
+ }
+
+ errors |= fpc_check_hwid();
+
+ rc = bio_algorithm_init();
+ if (rc < 0) {
+ errors |= FP_ERROR_INIT_FAIL;
+ CPRINTS("Error: bio_algorithm_init() failed, result=%d", rc);
+ }
+
+ /* Go back to low power */
+ fp_sensor_low_power();
+
+ return EC_SUCCESS;
+}
+
+/* Deinitialize the sensor IC */
+int fp_sensor_deinit(void)
+{
+ int rc;
+
+ rc = bio_algorithm_exit();
+ if (rc < 0)
+ CPRINTS("Error: bio_algorithm_exit() failed, result=%d", rc);
+
+ rc = fp_sensor_close();
+ if (rc < 0)
+ CPRINTS("Error: fp_sensor_close() failed, result=%d", rc);
+
+ return rc;
+}
+
+int fp_sensor_get_info(struct ec_response_fp_info *resp)
+{
+ int rc;
+
+ spi_buf[0] = FPC_CMD_HW_ID;
+
+ memcpy(resp, &ec_fp_sensor_info, sizeof(struct ec_response_fp_info));
+
+ rc = spi_transaction(SPI_FP_DEVICE, spi_buf, 3, spi_buf,
+ SPI_READBACK_ALL);
+ if (rc)
+ return EC_RES_ERROR;
+
+ resp->model_id = (spi_buf[1] << 8) | spi_buf[2];
+ resp->errors = errors;
+
+ return EC_SUCCESS;
+}
+
+int fp_finger_match(void *templ, uint32_t templ_count, uint8_t *image,
+ int32_t *match_index, uint32_t *update_bitmap)
+{
+ int rc;
+
+ rc = bio_template_image_match_list(templ, templ_count, image,
+ match_index, update_bitmap);
+ if (rc < 0)
+ CPRINTS("Error: bio_template_image_match_list() failed, result=%d",
+ rc);
+
+ return rc;
+}
+
+int fp_enrollment_begin(void)
+{
+ int rc;
+ bio_enrollment_t bio_enroll = enroll_ctx;
+
+ rc = bio_enrollment_begin(&bio_enroll);
+ if (rc < 0)
+ CPRINTS("Error: bio_enrollment_begin() failed, result=%d", rc);
+
+ return rc;
+}
+
+int fp_enrollment_finish(void *templ)
+{
+ int rc;
+ bio_enrollment_t bio_enroll = enroll_ctx;
+ bio_template_t bio_templ = templ;
+
+ rc = bio_enrollment_finish(bio_enroll, templ ? &bio_templ : NULL);
+ if (rc < 0)
+ CPRINTS("Error: bio_enrollment_finish() failed, result=%d", rc);
+
+ return rc;
+}
+
+int fp_finger_enroll(uint8_t *image, int *completion)
+{
+ int rc;
+ bio_enrollment_t bio_enroll = enroll_ctx;
+
+ rc = bio_enrollment_add_image(bio_enroll, image);
+ if (rc < 0) {
+ CPRINTS("Error: bio_enrollment_add_image() failed, result=%d",
+ rc);
+ return rc;
+ }
+
+ *completion = bio_enrollment_get_percent_complete(bio_enroll);
+
+ return rc;
+}
diff --git a/driver/fingerprint/fpc/bep/fpc_sensor_spi.c b/driver/fingerprint/fpc/bep/fpc_sensor_spi.c
new file mode 100644
index 0000000000..3db3713702
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/fpc_sensor_spi.c
@@ -0,0 +1,94 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* FPC Platform Abstraction Layer */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "console.h"
+#include "fpsensor.h"
+#include "fpc_sensor_spi.h"
+#include "gpio.h"
+#include "spi.h"
+#include "util.h"
+
+#include STRINGIFY(FP_SENSOR_PRIVATE)
+
+/* Console output macros */
+#define CPRINTF(format, args...) cprintf(CC_FP, format, ##args)
+#define CPRINTS(format, args...) cprints(CC_FP, format, ##args)
+
+#define SPI_BUF_SIZE (1024)
+
+#define FPC_RESULT_OK (0)
+#define FPC_RESULT_IO_ERROR (-8)
+
+static uint8_t spi_buf[SPI_BUF_SIZE] FP_FRAME_SECTION __aligned(4);
+
+int __unused fpc_sensor_spi_write_read(uint8_t *write, uint8_t *read,
+ size_t size, bool leave_cs_asserted)
+{
+ int rc = 0;
+
+ if (size == FP_SENSOR_REAL_IMAGE_SIZE) {
+ rc |= spi_transaction(SPI_FP_DEVICE, write, size, read,
+ SPI_READBACK_ALL);
+ spi_transaction_flush(SPI_FP_DEVICE);
+ } else if (size <= SPI_BUF_SIZE) {
+ memcpy(spi_buf, write, size);
+ rc |= spi_transaction_async(SPI_FP_DEVICE, spi_buf, size,
+ spi_buf, SPI_READBACK_ALL);
+
+ /* De-asserting the sensor chip-select will clear the sensor
+ * internal command state. To run multiple sensor transactions
+ * in the same command state (typically image capture), leave
+ * chip-select asserted. Make sure chip-select is de-asserted
+ * when all transactions are finished.
+ */
+ if (!leave_cs_asserted)
+ spi_transaction_flush(SPI_FP_DEVICE);
+ else
+ spi_transaction_wait(SPI_FP_DEVICE);
+
+ memcpy(read, spi_buf, size);
+ } else {
+ rc = -1;
+ }
+
+ if (rc == 0) {
+ return FPC_RESULT_OK;
+ } else {
+ CPRINTS("Error: spi_transaction()/spi_transaction_async() failed, result=%d",
+ rc);
+ return FPC_RESULT_IO_ERROR;
+ }
+}
+
+bool __unused fpc_sensor_spi_check_irq(void)
+{
+ return (gpio_get_level(GPIO_FPS_INT) == 1);
+}
+
+bool __unused fpc_sensor_spi_read_irq(void)
+{
+ return (gpio_get_level(GPIO_FPS_INT) == 1);
+}
+
+void __unused fpc_sensor_spi_reset(bool state)
+{
+ gpio_set_level(GPIO_FP_RST_ODL, state ? 0 : 1);
+}
+
+void __unused fpc_sensor_spi_init(uint32_t speed_hz)
+{
+}
+
+int __unused fpc_sensor_wfi(uint16_t timeout_ms, fpc_wfi_check_t enter_wfi,
+ bool enter_wfi_mode)
+{
+ return FPC_RESULT_OK;
+}
diff --git a/driver/fingerprint/fpc/bep/fpc_sensor_spi.h b/driver/fingerprint/fpc/bep/fpc_sensor_spi.h
new file mode 100644
index 0000000000..4b9bcd63a8
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/fpc_sensor_spi.h
@@ -0,0 +1,98 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_FPC_SENSOR_SPI_H
+#define __CROS_EC_FPC_SENSOR_SPI_H
+
+/**
+ * @file fpc_sensor_spi.h
+ * @brief Driver for SPI master.
+ *
+ * Driver for SPI master. Intended for communication with fingerprint sensor.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef bool (*fpc_wfi_check_t)(void);
+
+/**
+ * @brief Writes and reads SPI data.
+ *
+ * Writes data to SPI interface and reads data from SPI interface, with chip
+ * select control. The caller is blocked until the operation is complete. By use
+ * of the chip select control parameter a single SPI transaction can be split in
+ * several calls.
+ *
+ * @param[in] write Data to write. Must not be NULL if size > 0.
+ * @param[in,out] read Receive data buffer. The caller is responsible for
+ * allocating buffer. NULL => response is thrown away.
+ * @param[in] size Number of bytes to write (same as bytes received).
+ * 0 => Only chip select control.
+ * @param[in] leave_cs_asserted True => chip select is left in asserted
+ * state.
+ * False => chip select is de-asserted before
+ * return.
+ * @return ::fpc_bep_result_t
+ */
+int __unused fpc_sensor_spi_write_read(uint8_t *write, uint8_t *read,
+ size_t size, bool leave_cs_asserted);
+
+/**
+ * @brief Read sensor IRQ status.
+ *
+ * Returns status of the sensor IRQ.
+ *
+ * @return true if the sensor IRQ is currently active, otherwise false.
+ */
+bool __unused fpc_sensor_spi_check_irq(void);
+
+/**
+ * @brief Read sensor IRQ status and then set status to false.
+ *
+ * Returns status of the sensor IRQ and sets the status to false.
+ *
+ * @return true if the sensor IRQ has been active, otherwise false.
+ */
+bool __unused fpc_sensor_spi_read_irq(void);
+
+/**
+ * @brief Set sensor reset state.
+ *
+ * Set sensor reset state.
+ *
+ * @param[in] state Reset state.
+ * true => reset sensor, i.e. low GPIO state
+ * false => normal operation, i.e. high GPIO state
+ */
+void __unused fpc_sensor_spi_reset(bool state);
+
+/**
+ * @brief Initializes SPI master.
+ *
+ * @param[in] speed_hz Maximum SPI clock speed according to sensor HW spec
+ * (unit Hz).
+ *
+ */
+void __unused fpc_sensor_spi_init(uint32_t speed_hz);
+
+/**
+ * @brief Set system in WFI mode while waiting sensor IRQ.
+ *
+ * @note This mode only requires the system to be able to wake up from Sensor
+ * IRQ pin, all other peripheral can be turned off.
+ *
+ * @note The system time must be adjusted upon WFI return.
+ *
+ * @param[in] timeout_ms Time in ms before waking up, 0 if no timeout.
+ * @param[in] enter_wfi Function pointer to check WFI entry.
+ * @param[in] enter_wfi_mode Bool that is used when comparing the value returned
+ * by enter_wfi.
+ * @return FPC_RESULT_OK, FPC_RESULT_TIMEOUT
+ */
+int __unused fpc_sensor_wfi(uint16_t timeout_ms, fpc_wfi_check_t enter_wfi,
+ bool enter_wfi_mode);
+
+#endif /* __CROS_EC_FPC_SENSOR_SPI_H */
diff --git a/driver/fingerprint/fpc/bep/fpc_timebase.c b/driver/fingerprint/fpc/bep/fpc_timebase.c
new file mode 100644
index 0000000000..113e150ed9
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/fpc_timebase.c
@@ -0,0 +1,29 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* FPC Platform Abstraction Layer */
+
+#include <stdint.h>
+
+#include "fpc_timebase.h"
+#include "timer.h"
+
+uint32_t __unused fpc_timebase_get_tick(void)
+{
+ clock_t time;
+
+ time = clock();
+
+ return (uint32_t)time;
+}
+
+void __unused fpc_timebase_busy_wait(uint32_t ms)
+{
+ udelay(ms * 1000);
+}
+
+void __unused fpc_timebase_init(void)
+{
+}
diff --git a/driver/fingerprint/fpc/bep/fpc_timebase.h b/driver/fingerprint/fpc/bep/fpc_timebase.h
new file mode 100644
index 0000000000..388d13293e
--- /dev/null
+++ b/driver/fingerprint/fpc/bep/fpc_timebase.h
@@ -0,0 +1,48 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_FPC_TIMEBASE_H
+#define __CROS_EC_FPC_TIMEBASE_H
+
+/**
+ * @file fpc_timebase.h
+ * @brief Timebase based on a system tick.
+ *
+ * Supplies tick counter and wait operation(s).
+ */
+
+#include <stdint.h>
+
+#include "common.h"
+
+/**
+ * @brief Reads the system tick counter.
+ *
+ * @details To handle tick counter wrap around when checking for timeout, make
+ * sure to do the calculation in the following manner:
+ * "if ((current_tick - old_tick) > timeout) {"
+ * Example: current time (uint32_t) = 10 ticks
+ * old time (uint32_t) = 30 ticks before overflow of uint32_t
+ * current_time - old_time = 10 - (2**32 - 30) -> wraps around to 40
+ *
+ * @return Tick count since fpc_timebase_init() call. [ms]
+ */
+uint32_t __unused fpc_timebase_get_tick(void);
+
+/**
+ * @brief Busy wait.
+ *
+ * @param[in] ms Time to wait [ms].
+ * 0 => return immediately
+ * 1 => wait at least 1ms etc.
+ */
+void __unused fpc_timebase_busy_wait(uint32_t ms);
+
+/**
+ * @brief Initializes timebase. Starts system tick counter.
+ */
+void __unused fpc_timebase_init(void);
+
+#endif /* __CROS_EC_FPC_TIMEBASE_H */
diff --git a/driver/fingerprint/fpc/build.mk b/driver/fingerprint/fpc/build.mk
new file mode 100644
index 0000000000..ab6a6a4b9c
--- /dev/null
+++ b/driver/fingerprint/fpc/build.mk
@@ -0,0 +1,16 @@
+# Copyright 2019 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Build for FPC fingerprint drivers
+
+# Note that this variable includes the trailing "/"
+_fpc_cur_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
+
+ifeq ($(CONFIG_FP_SENSOR_FPC1145),rw)
+include $(_fpc_cur_dir)libfp/build.mk
+else ifeq ($(CONFIG_FP_SENSOR_FPC1025),rw)
+include $(_fpc_cur_dir)bep/build.mk
+else ifeq ($(CONFIG_FP_SENSOR_FPC1035),rw)
+include $(_fpc_cur_dir)bep/build.mk
+endif
diff --git a/driver/fingerprint/fpc/libfp/build.mk b/driver/fingerprint/fpc/libfp/build.mk
new file mode 100644
index 0000000000..8e745f728a
--- /dev/null
+++ b/driver/fingerprint/fpc/libfp/build.mk
@@ -0,0 +1,21 @@
+# Copyright 2019 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# FPC libfp source files build
+
+# Note that this variable includes the trailing "/"
+libfp_cur_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
+
+# Make sure output directory is created (in build directory)
+dirs-y+="$(libfp_cur_dir)"
+
+sensor-$(CONFIG_FP_SENSOR_FPC1145)=fpc1145
+
+# Only build for these objects for the RW image
+all-obj-rw+=$(libfp_cur_dir)fpc_sensor_pal.o \
+ $(libfp_cur_dir)fpc_private.o
+fp_sensor_header-rw=$(libfp_cur_dir)$(sensor-rw)_private.h
+
+CPPFLAGS+=-DFP_SENSOR_PRIVATE=$(fp_sensor_header-rw)
+CPPFLAGS+=-DFP_SENSOR_CONFIG=$(call uppercase,$(sensor-rw))
diff --git a/driver/fingerprint/fpc/libfp/fpc1145_private.h b/driver/fingerprint/fpc/libfp/fpc1145_private.h
new file mode 100644
index 0000000000..ad1e824942
--- /dev/null
+++ b/driver/fingerprint/fpc/libfp/fpc1145_private.h
@@ -0,0 +1,42 @@
+/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_FPC1145_PRIVATE_H
+#define __CROS_EC_FPC1145_PRIVATE_H
+
+#include <stdint.h>
+
+/* The 16-bit hardware ID is 0x140y */
+#define FP_SENSOR_HWID 0x140
+
+/* Sensor pixel resolution */
+#define FP_SENSOR_RES_Y 192
+#define FP_SENSOR_RES_X 56
+#define FP_SENSOR_RES_BPP 8
+
+/* Acquired finger frame definitions */
+#define FP_SENSOR_IMAGE_SIZE_MODE_VENDOR (35460)
+#define FP_SENSOR_IMAGE_SIZE_MODE_SIMPLE (13356)
+/*
+ * Size of the captured image in MQT mode. If you this is modified the
+ * corresponding value in the MQT tool fputils.py must be changed too.
+ * See b/111443750 for context.
+ */
+#define FP_SENSOR_IMAGE_SIZE_MODE_QUAL (24408)
+
+#define FP_SENSOR_IMAGE_SIZE FP_SENSOR_IMAGE_SIZE_MODE_VENDOR
+#define FP_SENSOR_IMAGE_OFFSET 2340
+
+/* Opaque FPC context */
+#define FP_SENSOR_CONTEXT_SIZE 4944
+
+/* Algorithm buffer sizes */
+#define FP_ALGORITHM_ENROLLMENT_SIZE 28
+#define FP_ALGORITHM_TEMPLATE_SIZE 47552
+
+/* Max number of templates stored / matched against */
+#define FP_MAX_FINGER_COUNT 5
+
+#endif /* __CROS_EC_FPC1145_PRIVATE_H */
diff --git a/driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h b/driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h
new file mode 100644
index 0000000000..9c00b14640
--- /dev/null
+++ b/driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h
@@ -0,0 +1,265 @@
+/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef BIOD_BIO_ALGORITHM_H_
+#define BIOD_BIO_ALGORITHM_H_
+
+#include <stdint.h>
+
+enum bio_algorithm_type {
+ BIO_ALGORITHM_FINGERPRINT,
+ BIO_ALGORITHM_IRIS,
+};
+/*
+ * An opaque pointer representing/uniquely identifying a sensor.
+ */
+typedef void *bio_sensor_t;
+/*
+ * An opaque pointer representing an image (scan).
+ */
+typedef void *bio_image_t;
+/*
+ * An opaque pointer representing/uniquely identifying an (serialized) enrolled
+ * template.
+ */
+typedef void *bio_template_t;
+/*
+ * An opaque pointer representing/uniquely identifying enrollment attempt.
+ */
+typedef void *bio_enrollment_t;
+/*
+ * Initializes biometric algorithm library. Should be the very first function
+ * to be invoked by the biometric daemon.
+ *
+ * Returns 0 on success, negative error code (such as -ENOMEM) on failure.
+ */
+int bio_algorithm_init(void);
+/*
+ * Instructs the biometric library to release all resources in preparation
+ * for the process termination (or unloading the library). Regardless of
+ * the returned error code the action is considered unrecoverable.
+ *
+ * Returns 0 on success, negative error code (such as -ENOMEM) on failure.
+ */
+int bio_algorithm_exit(void);
+/*
+ * Used to retrieve type of the algorithm library. Might be used by
+ * configuration processor module to match sensors and algorithm libraries.
+ */
+enum bio_algorithm_type bio_algorithm_get_type(void);
+/*
+ * Used to retrieve name of the algorithm library, to be used in diagnostics.
+ * Also might be used by configuration processor module to match sensors and
+ * algorithm libraries.
+ */
+const char *bio_algorithm_get_name(void);
+/*
+ * Used to retrieve version of the algorithm library, to be used in diagnostics.
+ */
+const char *bio_algorithm_get_version(void);
+/*
+ * Used to retrieve additional information from the algorithm library, to be
+ * used in diagnostics.
+ */
+const char *bio_algorithm_get_banner(void);
+/*
+ * Initializes a new sensor structure and returns its handle that will be used
+ * in other calls to identify the sensor involved in the operation.
+ *
+ * Returns 0 on success, negative error code (such as -ENOMEM) on failure.
+ */
+int bio_sensor_create(bio_sensor_t *sensor);
+/*
+ * Releases all resources held by the library in conjunction with given sensor.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_sensor_destroy(bio_sensor_t sensor);
+/*
+ * Communicates particulars of a given sensor so that algorithm library can
+ * adjust its behavior as needed.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_sensor_set_model(bio_sensor_t sensor, uint32_t vendor_id,
+ uint32_t product_id, uint32_t model_id,
+ uint32_t version);
+/*
+ * Communicates format of data used by given sensor to the algorithm library.
+ * This is a fourcc value defined by V4L2 API.
+ * Could be a new define for biometric sensors or V4L2_PIX_FMT_GREY.
+ * Algorithm library will return error if it can not work with given format.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_sensor_set_format(bio_sensor_t sensor, uint32_t pixel_format);
+/*
+ * Communicates dimensions of given sensor to the algorithm library.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_sensor_set_size(bio_sensor_t sensor, uint32_t width, uint32_t height);
+/*
+ * Instructs the algorithm library to initialize a new structure to hold
+ * biometric image of given dimensions acquired from given sensor.
+ * It will return image handle that will be used in other calls to identify
+ * the image involved in the operation.
+ *
+ * Returns 0 on success, negative error code (such as -ENOMEM) on failure.
+ */
+int bio_image_create(bio_sensor_t sensor, uint32_t width, uint32_t height,
+ bio_image_t *image);
+/*
+ * Communicates dimensions of image to the algorithm library.
+ * Can be used if image is less than full sensor resolution.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_image_set_size(bio_image_t image, uint32_t width, uint32_t height);
+/*
+ * Attaches data from biometric sensor to image structure. The caller must
+ * ensure that there is enough of data for given image dimensions for given
+ * format used by the sensor.
+ *
+ * It is assumes that the data pointer stays valid until bio_image_destroy()
+ * is called.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_image_set_data(bio_image_t image, const uint8_t *data, size_t size);
+/*
+ * Releases all resources held by the library in conjunction with given image.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_image_destroy(bio_image_t image);
+
+/*
+ * Compares given biometric image against a list of enrolled template(s).
+ * In case the image match a template the match_index will indicate which
+ * template in the list that matched.
+ * The algorithm library can update templates with additional biometric data
+ * from the image, if it chooses to do so. The updated template(s) will be
+ * indicated by the out parameter 'updated_templates', a bit-field where
+ * updated template(s) indicated by the corresponding bit being set
+ * Returns:
+ * - negative value on error
+ * - BIO_TEMPLATE_NO_MATCH on non-match
+ * - BIO_TEMPLATE_MATCH for match when template was not updated with new data
+ * - BIO_TEMPLATE_MATCH_UPDATED for match when template was updated
+ * - BIO_TEMPLATE_MATCH_UPDATE_FAILED match, but update failed (do not save)
+ * - BIO_TEMPLATE_LOW_QUALITY when matching could not be performed due to low
+ * image quality
+ * - BIO_TEMPLATE_LOW_COVERAGE when matching could not be performed due to
+ * finger covering too little area of the sensor
+ */
+int bio_template_image_match_list(bio_template_t tmpl, uint32_t num_templates,
+ bio_image_t image, int32_t *match_index,
+ uint32_t *updated_templates);
+int bio_template_image_match(bio_template_t tmpl, bio_image_t image);
+/*
+ * Returns size of template data in serialized form.
+ *
+ * Returns negative error code (such as -EINVAL) on failure, or size of the
+ * serialized form in bytes.
+ */
+ssize_t bio_template_get_serialized_size(bio_template_t tmpl);
+/*
+ * Releases all resources held by the library in conjunction with given
+ * template.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_template_destroy(bio_template_t tmpl);
+/*
+ * Initiates biometric data enrollment process. Algorithm library returns
+ * 'enrollment handle' that is used for all subsequent enrollment operations.
+ *
+ * Returns 0 on success, negative error code (such as -ENOMEM) on failure.
+ */
+int bio_enrollment_begin(bio_sensor_t sensor, bio_enrollment_t *enrollment);
+/*
+ * Adds fingerprint image to an enrollment.
+ *
+ * The library should expect to copy any relevant data from the “image”
+ * as it is likely to be destroyed (via bio_image_destroy() call) shortly after
+ * this call completes.
+ *
+ * Returns:
+ * - negative value on error
+ * - BIO_ENROLLMENT_OK when image was successfully enrolled
+ * - BIO_ENROLLMENT_IMMOBILE when image added, but user should be advised
+ * to move finger
+ * - BIO_ENROLLMENT_LOW_QUALITY when image could not be used due to low
+ * image quality
+ * - BIO_ENROLLMENT_LOW_COVERAGE when image could not be used due to
+ * finger covering too little area of the sensor
+ */
+#define BIO_ENROLLMENT_OK 0
+#define BIO_ENROLLMENT_IMMOBILE 2
+#define BIO_ENROLLMENT_LOW_QUALITY 1
+#define BIO_ENROLLMENT_LOW_COVERAGE 3
+/* Can be used to detect if image was usable for enrollment or not. */
+#define BIO_ENROLLMENT_PROBLEM_MASK 1
+int bio_enrollment_add_image(bio_enrollment_t enrollment, bio_image_t image);
+/*
+ * Indicates whether there is enough data in the enrollment for it to be
+ * converted into a template to be used for identification.
+ *
+ * Returns 0 for if enrollment does not have enough data yet, 1 if enrollment
+ * is complete, or negative error code (such as -EINVAL) on failure.
+ *
+ */
+int bio_enrollment_is_complete(bio_enrollment_t enrollment);
+/*
+ * Returns percent of coverage accumulated during enrollment process.
+ * Optional method. Regardless of value returned by this call user should call
+ * bio_enrollment_is_complete() to check if algorithm library accumulated enough
+ * data to create a template.
+ *
+ * Returns value in the range 0..100, or negative error (such as -EINVAL);
+ */
+int bio_enrollment_get_percent_complete(bio_enrollment_t enrollment);
+/*
+ * Indicates that given enrollment process is complete, and algorithm library
+ * should generate an active template that can be used in subsequent calls
+ * to bio_image_match() and bio_template_serialize() from enrollment data.
+ * After the template is created the library should release all resources
+ * associated with this enrollment.
+ *
+ * Argument 'tmpl' is optional and can be set to NULL if caller wishes to
+ * abort enrollment process.
+ *
+ * Returns 0 on success, negative error code (such as -EINVAL) on failure.
+ */
+int bio_enrollment_finish(bio_enrollment_t enrollment, bio_template_t *tmpl);
+
+typedef struct {
+ int32_t coverage; /* Sensor coverage in range [0..100] */
+ int32_t quality; /* Image quality in range [0..100] */
+ int32_t min_coverage; /* Minimum coverage accepted by enroll */
+ int32_t min_quality; /* Minimum image quality accepted by enroll */
+} bio_image_status_t;
+
+/*
+ * Get the image quality and threshold values for a bio_image_t
+ *
+ * @param[in] image Image data as acquired by
+ * fp_sensor_acquire_image_with_mode
+ * @param[out] image_status Populated structure with quality/coverage values
+ * and corresponding threshold values
+ *
+ * @note This function will alter the internal states of the bio algorithm
+ * library and must not be used during an enroll sequence. The typical
+ * use case for this function is to qualify images during image
+ * collection.
+ *
+ * @return negative on error.
+ * @return 0 if the quality and coverage threshold values aren't reached.
+ * @return 1 if the quality and coverage threshold values are reached.
+ */
+int bio_sensor_get_image_status(bio_image_t image,
+ bio_image_status_t *image_status);
+
+#endif /* BIOD_BIO_ALGORITHM_H_ */
diff --git a/driver/fingerprint/fpc/libfp/fpc_private.c b/driver/fingerprint/fpc/libfp/fpc_private.c
new file mode 100644
index 0000000000..1ee7f29a79
--- /dev/null
+++ b/driver/fingerprint/fpc/libfp/fpc_private.c
@@ -0,0 +1,317 @@
+/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <stddef.h>
+#include "common.h"
+#include "console.h"
+#include "endian.h"
+#include "fpc_bio_algorithm.h"
+#include "fpc_private.h"
+#include "fpsensor.h"
+#include "gpio.h"
+#include "link_defs.h"
+#include "spi.h"
+#include "system.h"
+#include "timer.h"
+#include "util.h"
+
+#include STRINGIFY(FP_SENSOR_PRIVATE)
+
+#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_FP, format, ## args)
+
+#define FP_SENSOR_NAME STRINGIFY(FP_SENSOR_CONFIG)
+
+/* Minimum reset duration */
+#define FP_SENSOR_RESET_DURATION_US (10 * MSEC)
+/* Maximum delay for the interrupt to be asserted after the sensor is reset */
+#define FP_SENSOR_IRQ_MAX_DELAY_US (5 * MSEC)
+/* Maximum number of attempts to initialise the sensor */
+#define FP_SENSOR_MAX_INIT_ATTEMPTS 10
+/* Delay between failed attempts of fp_sensor_open() */
+#define FP_SENSOR_OPEN_DELAY_US (500 * MSEC)
+
+/* Decode internal error codes from FPC's sensor library */
+#define FPC_GET_INTERNAL_CODE(res) (((res) & 0x000fc000) >> 14)
+/* There was a finger on the sensor when calibrating finger detect */
+#define FPC_INTERNAL_FINGER_DFD FPC_ERROR_INTERNAL_38
+
+/*
+ * The sensor context is uncached as it contains the SPI buffers,
+ * the binary library assumes that it is aligned.
+ */
+static uint8_t ctx[FP_SENSOR_CONTEXT_SIZE] __uncached __aligned(4);
+static bio_sensor_t bio_sensor;
+static uint8_t enroll_ctx[FP_ALGORITHM_ENROLLMENT_SIZE];
+
+/* recorded error flags */
+static uint16_t errors;
+
+/* Sensor description */
+static struct ec_response_fp_info fpc1145_info = {
+ /* Sensor identification */
+ .vendor_id = FOURCC('F', 'P', 'C', ' '),
+ .product_id = 9,
+ .model_id = 1,
+ .version = 1,
+ /* Image frame characteristics */
+ .frame_size = FP_SENSOR_IMAGE_SIZE,
+ .pixel_format = V4L2_PIX_FMT_GREY,
+ .width = FP_SENSOR_RES_X,
+ .height = FP_SENSOR_RES_Y,
+ .bpp = FP_SENSOR_RES_BPP,
+};
+
+/* Sensor IC commands */
+enum fpc_cmd {
+ FPC_CMD_STATUS = 0x14,
+ FPC_CMD_INT_STS = 0x18,
+ FPC_CMD_INT_CLR = 0x1C,
+ FPC_CMD_FINGER_QUERY = 0x20,
+ FPC_CMD_SLEEP = 0x28,
+ FPC_CMD_DEEPSLEEP = 0x2C,
+ FPC_CMD_SOFT_RESET = 0xF8,
+ FPC_CMD_HW_ID = 0xFC,
+};
+
+/* Maximum size of a sensor command SPI transfer */
+#define MAX_CMD_SPI_TRANSFER_SIZE 3
+
+/* Uncached memory for the SPI transfer buffer */
+static uint8_t spi_buf[MAX_CMD_SPI_TRANSFER_SIZE] __uncached;
+
+static int fpc_send_cmd(const uint8_t cmd)
+{
+ spi_buf[0] = cmd;
+ return spi_transaction(SPI_FP_DEVICE, spi_buf, 1, spi_buf,
+ SPI_READBACK_ALL);
+}
+
+void fp_sensor_low_power(void)
+{
+ /*
+ * TODO(b/117620462): verify that sleep mode is WAI (no increased
+ * latency, expected power consumption).
+ */
+ if (0)
+ fpc_send_cmd(FPC_CMD_SLEEP);
+}
+
+static int fpc_check_hwid(void)
+{
+ uint16_t id;
+ int rc;
+
+ /* Clear previous occurences of relevant |errors| flags. */
+ errors &= (~FP_ERROR_SPI_COMM & ~FP_ERROR_BAD_HWID);
+
+ spi_buf[0] = FPC_CMD_HW_ID;
+ rc = spi_transaction(SPI_FP_DEVICE, spi_buf, 3, spi_buf,
+ SPI_READBACK_ALL);
+ if (rc) {
+ CPRINTS("FPC ID read failed %d", rc);
+ errors |= FP_ERROR_SPI_COMM;
+ return EC_ERROR_HW_INTERNAL;
+ }
+ id = (spi_buf[1] << 8) | spi_buf[2];
+ if ((id >> 4) != FP_SENSOR_HWID) {
+ CPRINTS("FPC unknown silicon 0x%04x", id);
+ errors |= FP_ERROR_BAD_HWID;
+ return EC_ERROR_HW_INTERNAL;
+ }
+ CPRINTS(FP_SENSOR_NAME " id 0x%04x", id);
+
+ return EC_SUCCESS;
+}
+
+static uint8_t fpc_read_clear_int(void)
+{
+ spi_buf[0] = FPC_CMD_INT_CLR;
+ spi_buf[1] = 0xff;
+ if (spi_transaction(SPI_FP_DEVICE, spi_buf, 2, spi_buf,
+ SPI_READBACK_ALL))
+ return 0xff;
+ return spi_buf[1];
+}
+
+/*
+ * Toggle the h/w reset pins and clear any pending IRQs before initializing the
+ * sensor contexts.
+ * Returns:
+ * - EC_SUCCESS on success.
+ * - EC_ERROR_HW_INTERNAL on failure (and |errors| variable is updated where
+ * appropriate).
+ */
+static int fpc_pulse_hw_reset(void)
+{
+ int ret;
+ int rc = EC_SUCCESS;
+ /* Clear previous occurrence of possible error flags. */
+ errors &= ~FP_ERROR_NO_IRQ;
+
+ /* Ensure we pulse reset low to initiate the startup */
+ gpio_set_level(GPIO_FP_RST_ODL, 0);
+ usleep(FP_SENSOR_RESET_DURATION_US);
+ gpio_set_level(GPIO_FP_RST_ODL, 1);
+ /* the IRQ line should be set high by the sensor */
+ usleep(FP_SENSOR_IRQ_MAX_DELAY_US);
+ if (!gpio_get_level(GPIO_FPS_INT)) {
+ CPRINTS("Sensor IRQ not ready");
+ errors |= FP_ERROR_NO_IRQ;
+ rc = EC_ERROR_HW_INTERNAL;
+ }
+
+ /* Check the Hardware ID */
+ ret = fpc_check_hwid();
+ if (ret != EC_SUCCESS) {
+ CPRINTS("Failed to verify HW ID");
+ rc = EC_ERROR_HW_INTERNAL;
+ }
+
+ /* clear the pending 'ready' IRQ before enabling interrupts */
+ fpc_read_clear_int();
+
+ return rc;
+}
+
+/* Reset and initialize the sensor IC */
+int fp_sensor_init(void)
+{
+ int res;
+ int attempt;
+
+ errors = FP_ERROR_DEAD_PIXELS_UNKNOWN;
+
+ /* Release any previously held resources from earlier iterations */
+ res = bio_sensor_destroy(bio_sensor);
+ if (res)
+ CPRINTS("FPC Sensor resources release failed: %d", res);
+ bio_sensor = NULL;
+
+ res = bio_algorithm_exit();
+ if (res)
+ CPRINTS("FPC Algorithm resources release failed: %d", res);
+
+ /* Print the binary libfpsensor.a library version */
+ CPRINTF("FPC libfpsensor.a v%s\n", fp_sensor_get_version());
+ cflush();
+
+ attempt = 0;
+ do {
+ attempt++;
+
+ res = fpc_pulse_hw_reset();
+ if (res != EC_SUCCESS) {
+ /* In case of failure, retry after a delay. */
+ CPRINTS("H/W sensor reset failed, error flags: 0x%x",
+ errors);
+ cflush();
+ usleep(FP_SENSOR_OPEN_DELAY_US);
+ continue;
+ }
+
+ /*
+ * Ensure that any previous context data is obliterated in case
+ * of a sensor reset.
+ */
+ memset(ctx, 0, FP_SENSOR_CONTEXT_SIZE);
+
+ res = fp_sensor_open(ctx, FP_SENSOR_CONTEXT_SIZE);
+ /* Flush messages from the PAL if any */
+ cflush();
+ CPRINTS("Sensor init (attempt %d): 0x%x", attempt, res);
+ /*
+ * Retry on failure. This typically happens if the user has left
+ * their finger on the sensor after powering up the device, DFD
+ * will fail in that case. We've seen other error modes in the
+ * field, retry in all cases to be more resilient.
+ */
+ if (!res)
+ break;
+ usleep(FP_SENSOR_OPEN_DELAY_US);
+ } while (attempt < FP_SENSOR_MAX_INIT_ATTEMPTS);
+ if (res)
+ errors |= FP_ERROR_INIT_FAIL;
+
+ res = bio_algorithm_init();
+ /* the PAL might have spewed a lot of traces, ensure they are visible */
+ cflush();
+ CPRINTS("Algorithm init: 0x%x", res);
+ if (res < 0)
+ errors |= FP_ERROR_INIT_FAIL;
+ res = bio_sensor_create(&bio_sensor);
+ CPRINTS("Sensor create: 0x%x", res);
+ if (res < 0)
+ errors |= FP_ERROR_INIT_FAIL;
+
+ /* Go back to low power */
+ fp_sensor_low_power();
+
+ return EC_SUCCESS;
+}
+
+/* Deinitialize the sensor IC */
+int fp_sensor_deinit(void)
+{
+ /*
+ * TODO(tomhughes): libfp doesn't have fp_sensor_close like BEP does.
+ * We'll need FPC to either add it or verify that we don't have the same
+ * problem with the libfp library as described in:
+ * b/124773209#comment46
+ */
+ return EC_SUCCESS;
+}
+
+int fp_sensor_get_info(struct ec_response_fp_info *resp)
+{
+ int rc;
+
+ memcpy(resp, &fpc1145_info, sizeof(*resp));
+
+ spi_buf[0] = FPC_CMD_HW_ID;
+ rc = spi_transaction(SPI_FP_DEVICE, spi_buf, 3, spi_buf,
+ SPI_READBACK_ALL);
+ if (rc)
+ return EC_RES_ERROR;
+ resp->model_id = (spi_buf[1] << 8) | spi_buf[2];
+ resp->errors = errors;
+
+ return EC_SUCCESS;
+}
+
+int fp_finger_match(void *templ, uint32_t templ_count, uint8_t *image,
+ int32_t *match_index, uint32_t *update_bitmap)
+{
+ return bio_template_image_match_list(templ, templ_count, image,
+ match_index, update_bitmap);
+}
+
+int fp_enrollment_begin(void)
+{
+ int rc;
+ bio_enrollment_t p = enroll_ctx;
+
+ rc = bio_enrollment_begin(bio_sensor, &p);
+ if (rc < 0)
+ CPRINTS("begin failed %d", rc);
+ return rc;
+}
+
+int fp_enrollment_finish(void *templ)
+{
+ bio_template_t pt = templ;
+
+ return bio_enrollment_finish(enroll_ctx, templ ? &pt : NULL);
+}
+
+int fp_finger_enroll(uint8_t *image, int *completion)
+{
+ int rc = bio_enrollment_add_image(enroll_ctx, image);
+
+ if (rc < 0)
+ return rc;
+ *completion = bio_enrollment_get_percent_complete(enroll_ctx);
+ return rc;
+}
diff --git a/driver/fingerprint/fpc/libfp/fpc_private.h b/driver/fingerprint/fpc/libfp/fpc_private.h
new file mode 100644
index 0000000000..6ec09ee0ee
--- /dev/null
+++ b/driver/fingerprint/fpc/libfp/fpc_private.h
@@ -0,0 +1,104 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Private sensor interface */
+
+#ifndef __CROS_EC_FPC_PRIVATE_H
+#define __CROS_EC_FPC_PRIVATE_H
+
+/* External error codes from FPC's sensor library */
+enum fpc_error_code_external {
+ FPC_ERROR_NONE = 0,
+ FPC_ERROR_NOT_FOUND = 1,
+ FPC_ERROR_CAN_BE_USED_2 = 2,
+ FPC_ERROR_CAN_BE_USED_3 = 3,
+ FPC_ERROR_CAN_BE_USED_4 = 4,
+ FPC_ERROR_PAL = 5,
+ FPC_ERROR_IO = 6,
+ FPC_ERROR_CANCELLED = 7,
+ FPC_ERROR_UNKNOWN = 8,
+ FPC_ERROR_MEMORY = 9,
+ FPC_ERROR_PARAMETER = 10,
+ FPC_ERROR_TEST_FAILED = 11,
+ FPC_ERROR_TIMEDOUT = 12,
+ FPC_ERROR_SENSOR = 13,
+ FPC_ERROR_SPI = 14,
+ FPC_ERROR_NOT_SUPPORTED = 15,
+ FPC_ERROR_OTP = 16,
+ FPC_ERROR_STATE = 17,
+ FPC_ERROR_PN = 18,
+ FPC_ERROR_DEAD_PIXELS = 19,
+ FPC_ERROR_TEMPLATE_CORRUPTED = 20,
+ FPC_ERROR_CRC = 21,
+ FPC_ERROR_STORAGE = 22, /**< Errors related to storage **/
+ FPC_ERROR_MAXIMUM_REACHED = 23, /**< The allowed maximum has been reached **/
+ FPC_ERROR_MINIMUM_NOT_REACHED = 24, /**< The required minimum was not reached **/
+ FPC_ERROR_SENSOR_LOW_COVERAGE = 25, /**< Minimum sensor coverage was not reached **/
+ FPC_ERROR_SENSOR_LOW_QUALITY = 26, /**< Sensor image is considered low quality **/
+ FPC_ERROR_SENSOR_FINGER_NOT_STABLE = 27, /**< Finger was not stable during image capture **/
+};
+
+/* Internal error codes from FPC's sensor library */
+enum fpc_error_code_internal {
+ FPC_ERROR_INTERNAL_0 = 0, /* Indicates that no internal code was set. */
+ FPC_ERROR_INTERNAL_1 = 1, /* Not supported by sensor. */
+ FPC_ERROR_INTERNAL_2 = 2, /* Sensor got a NULL response (from other module). */
+ FPC_ERROR_INTERNAL_3 = 3, /* Runtime config not supported by firmware. */
+ FPC_ERROR_INTERNAL_4 = 4, /* CAC has not been created. */
+ FPC_ERROR_INTERNAL_5 = 5, /* CAC returned an error to the sensor. */
+ FPC_ERROR_INTERNAL_6 = 6, /* CAC fasttap image capture failed. */
+ FPC_ERROR_INTERNAL_7 = 7, /* CAC fasttap image capture failed. */
+ FPC_ERROR_INTERNAL_8 = 8, /* CAC Simple image capture failed. */
+ FPC_ERROR_INTERNAL_9 = 9, /* CAC custom image capture failed. */
+ FPC_ERROR_INTERNAL_10 = 10, /* CAC MQT image capture failed. */
+ FPC_ERROR_INTERNAL_11 = 11, /* CAC PN image capture failed. */
+ FPC_ERROR_INTERNAL_12 = 12, /* Reading CAC context size. */
+ FPC_ERROR_INTERNAL_13 = 13, /* Reading CAC context size. */
+ FPC_ERROR_INTERNAL_14 = 14, /* Sensor context invalid. */
+ FPC_ERROR_INTERNAL_15 = 15, /* Buffer reference is invalid. */
+ FPC_ERROR_INTERNAL_16 = 16, /* Buffer size reference is invalid. */
+ FPC_ERROR_INTERNAL_17 = 17, /* Image data reference is invalid. */
+ FPC_ERROR_INTERNAL_18 = 18, /* Capture type specified is invalid. */
+ FPC_ERROR_INTERNAL_19 = 19, /* Capture config specified is invalid. */
+ FPC_ERROR_INTERNAL_20 = 20, /* Sensor type in hw desc could not be extracted. */
+ FPC_ERROR_INTERNAL_21 = 21, /* Failed to create BNC component. */
+ FPC_ERROR_INTERNAL_22 = 22, /* BN calibration failed. */
+ FPC_ERROR_INTERNAL_23 = 23, /* BN memory allocation failed. */
+ FPC_ERROR_INTERNAL_24 = 24, /* Companion type in hw desc could not be extracted. */
+ FPC_ERROR_INTERNAL_25 = 25, /* Coating type in hw desc could not be extracted. */
+ FPC_ERROR_INTERNAL_26 = 26, /* Sensor mode type is invalid. */
+ FPC_ERROR_INTERNAL_27 = 27, /* Wrong Sensor state in OTP read. */
+ FPC_ERROR_INTERNAL_28 = 28, /* Mismatch of register size in overlay vs rrs. */
+ FPC_ERROR_INTERNAL_29 = 29, /* Checkerboard capture failed. */
+ FPC_ERROR_INTERNAL_30 = 30, /* Error converting to fpc_image in dp calibration. */
+ FPC_ERROR_INTERNAL_31 = 31, /* Failed to capture reset pixel image. */
+ FPC_ERROR_INTERNAL_32 = 32, /* API level not support in dp calibration. */
+ FPC_ERROR_INTERNAL_33 = 33, /* The image data in parameter is invalid. */
+ FPC_ERROR_INTERNAL_34 = 34, /* PAL delay function has failed. */
+ FPC_ERROR_INTERNAL_35 = 35, /* AFD sensor commad did not complete. */
+ FPC_ERROR_INTERNAL_36 = 36, /* AFD wrong runlevel detected after calibration. */
+ FPC_ERROR_INTERNAL_37 = 37, /* Wrong rrs size. */
+ FPC_ERROR_INTERNAL_38 = 38, /* There was a finger on the sensor when calibrating finger detect. */
+ FPC_ERROR_INTERNAL_39 = 39, /* The calculated calibration value is larger than max. */
+ FPC_ERROR_INTERNAL_40 = 40, /* The sensor fifo always underflows */
+ FPC_ERROR_INTERNAL_41 = 41, /* The oscillator calibration resulted in a too high or low value */
+ FPC_ERROR_INTERNAL_42 = 42, /* Sensor driver was opened with NULL configuration */
+ FPC_ERROR_INTERNAL_43 = 43, /* Sensor driver as opened with NULL hw descriptor */
+ FPC_ERROR_INTERNAL_44 = 44, /* Error occured during image drive test */
+};
+
+/* FPC specific initialization function to fill their context */
+int fp_sensor_open(void *ctx, uint32_t ctx_size);
+
+/*
+ * Get library version code.
+ * version code contains three digits. x.y.z
+ * x - major version
+ * y - minor version
+ * z - build index
+ */
+const char *fp_sensor_get_version(void);
+
+#endif /* __CROS_EC_FPC_PRIVATE_H */
diff --git a/driver/fingerprint/fpc/libfp/fpc_sensor_pal.c b/driver/fingerprint/fpc/libfp/fpc_sensor_pal.c
new file mode 100644
index 0000000000..35c07b464a
--- /dev/null
+++ b/driver/fingerprint/fpc/libfp/fpc_sensor_pal.c
@@ -0,0 +1,60 @@
+/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/* FPC Platform Abstraction Layer callbacks */
+
+#include "common.h"
+#include "console.h"
+#include "fpsensor.h"
+#include "fpc_sensor_pal.h"
+#include "shared_mem.h"
+#include "spi.h"
+#include "timer.h"
+#include "uart.h"
+#include "util.h"
+
+#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_FP, format, ## args)
+
+void fpc_pal_log_entry(const char *tag, int log_level, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ uart_puts(tag);
+ uart_vprintf(format, args);
+ va_end(args);
+}
+
+int fpc_pal_delay_us(uint64_t us)
+{
+ if (us > 250)
+ usleep(us);
+ else
+ udelay(us);
+ return 0;
+}
+
+int fpc_pal_spi_writeread(fpc_device_t device, uint8_t *tx_buf, uint8_t *rx_buf,
+ uint32_t size)
+{
+ return spi_transaction(SPI_FP_DEVICE, tx_buf, size, rx_buf,
+ SPI_READBACK_ALL);
+}
+
+int fpc_pal_wait_irq(fpc_device_t device, fpc_pal_irq_t irq_type)
+{
+ /* TODO: b/72360575 */
+ return EC_SUCCESS; /* just lie about it, libfpsensor prefers... */
+}
+
+int32_t FpcMalloc(void **data, size_t size)
+{
+ return shared_mem_acquire(size, (char **)data);
+}
+
+void FpcFree(void **data)
+{
+ shared_mem_release(*data);
+}
diff --git a/driver/fingerprint/fpc/libfp/fpc_sensor_pal.h b/driver/fingerprint/fpc/libfp/fpc_sensor_pal.h
new file mode 100644
index 0000000000..78376863f1
--- /dev/null
+++ b/driver/fingerprint/fpc/libfp/fpc_sensor_pal.h
@@ -0,0 +1,118 @@
+/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef FPC_PAL_SENSOR_H_
+#define FPC_PAL_SENSOR_H_
+
+#include <stdint.h>
+
+typedef void *fpc_device_t;
+
+/**
+ * @brief Used to describe an interrupt
+ */
+typedef enum {
+ IRQ_INT_TRIG = 0x01, /**< Internally triggered by sensor (fast interrupt) **/
+ IRQ_EXT_TRIG = 0x02 /**< Externally triggered by event outside sensor (may take long time) **/
+} fpc_pal_irq_t;
+
+/**
+ * @brief Write sensor access buffer to SPI interface
+ *
+ * @param[in] device Client's device handle.
+ * @param[in] access_buffer Buffer holding data to write.
+ * @param[in] access_buffer_size Size of the access buffer.
+ *
+ * @return 0 on success.
+ * negative value on error.
+ */
+int fpc_pal_spi_write(fpc_device_t device, uint8_t *access_buffer,
+ uint32_t access_buffer_size);
+
+/**
+ * @brief Write and read sensor access buffer to SPI interface
+ *
+ * SPI transfers always write the same number of bytes as they read,
+ * hence the size of tx_buffer and rx_buffer must be the same.
+ *
+ * @param[in] device Client's device handle.
+ * @param[in] tx_buffer Buffer holding data to write.
+ * @param[in] rx_buffer Buffer where read data will be stored.
+ * @param[in] size Size of tx and rx buffer.
+ *
+ * @return 0 on success.
+ * negative value on error.
+ */
+int fpc_pal_spi_writeread(fpc_device_t device, uint8_t *tx_buffer,
+ uint8_t *rx_buffer, uint32_t size);
+
+/**
+ * @brief Wait for IRQ
+ *
+ * @param[in] device Client's device handle.
+ * @param[in] irq_type The expected IRQ type.
+ *
+ * @return 0 on success.
+ * negative value on error.
+ */
+int fpc_pal_wait_irq(fpc_device_t device, fpc_pal_irq_t irq_type);
+
+/**
+ * @brief Get time
+ *
+ * @param[out] time_us Timestamp in microseconds.
+ *
+ * Not all platforms have microsecond resolution. These should
+ * return time in terms of hole milliseconds.
+ *
+ * @return 0 on success.
+ * negative value on error.
+ */
+int fpc_pal_get_time(uint64_t *time_us);
+
+/**
+ * @brief Delay function
+ *
+ * @param[in] us Delay in microseconds.
+ *
+ * Not all platforms have microsecond resolution. These should
+ * delay in terms of hole milliseconds.
+ *
+ * @return 0 on success.
+ * negative value on error.
+ */
+int fpc_pal_delay_us(uint64_t us);
+
+/**
+ * @brief Get platform SPI clock frequency
+ *
+ * @param[in] device Client's device handle.
+ * @param[out] speed_hz SPI frequency in hertz.
+ *
+ * Required by platform for adaptive SPI calculations.
+ *
+ * @return 0 on success.
+ * negative value on error.
+ */
+int fpc_pal_spi_get_speed_hz(fpc_device_t device, uint32_t *speed_hz);
+
+/**
+ * @brief Print SDK log strings
+ *
+ * @param[in] tag sensor sdk log prefix
+ * @param[in] log_level FPC_SENSOR_SDK_LOG_LEVEL_DEBUG - debug print
+ * FPC_SENSOR_SDK_LOG_LEVEL_INFO - information print
+ * FPC_SENSOR_SDK_LOG_LEVEL_ERROR - error print
+ * @param[in] format the format specifier.
+ * @param[in] ... additional arguments.
+ *
+ */
+#define FPC_SENSOR_SDK_LOG_LEVEL_DEBUG (1)
+#define FPC_SENSOR_SDK_LOG_LEVEL_INFO (2)
+#define FPC_SENSOR_SDK_LOG_LEVEL_ERROR (3)
+#define FPC_SENSOR_SDK_LOG_LEVEL_DISABLED (4)
+void fpc_pal_log_entry(const char *tag, int log_level, const char *format, ...);
+
+#endif // FPC_PAL_SENSOR_H_