diff options
Diffstat (limited to 'driver/fpc1140.c')
-rw-r--r-- | driver/fpc1140.c | 342 |
1 files changed, 0 insertions, 342 deletions
diff --git a/driver/fpc1140.c b/driver/fpc1140.c deleted file mode 100644 index 7b48158887..0000000000 --- a/driver/fpc1140.c +++ /dev/null @@ -1,342 +0,0 @@ -/* 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 "atomic.h" -#include "common.h" -#include "console.h" -#include "ec_commands.h" -#include "endian.h" -#include "gpio.h" -#include "host_command.h" -#include "mkbp_event.h" -#include "spi.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#ifdef HAVE_PRIVATE -#include "fpc1145_private.h" - -uint8_t fp_buffer[FPC_IMAGE_SIZE]; -#endif - -#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args) -#define CPRINTS(format, args...) cprints(CC_FP, format, ## args) - -/* 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 = 0x2B, - FPC_CMD_SOFT_RESET = 0xF8, - FPC_CMD_HW_ID = 0xFC, -}; - -#define FPC_IDLE_MASK 0x1E - -#define FPC_INT_FINGER_DOWN (1 << 0) - -#ifndef SPI_FPC_DEVICE -#define SPI_FPC_DEVICE (&spi_devices[0]) -#endif - -static uint32_t fp_events; -static uint32_t sensor_mode; - -/* Opaque sensor configuration registers settings */ -static union { - struct ec_params_fp_sensor_config sensor_config; - uint8_t data[0x220]; -} u; - -static int fpc_send_cmd(const uint8_t cmd) -{ - return spi_transaction(SPI_FPC_DEVICE, &cmd, 1, NULL, 0); -} - -static int fpc_check_hwid(void) -{ - const uint8_t cmd = FPC_CMD_HW_ID; - uint16_t id; - int rc; - - rc = spi_transaction(SPI_FPC_DEVICE, &cmd, 1, (void *)&id, sizeof(id)); - if (rc) { - CPRINTS("FPC ID read failed %d", rc); - return rc; - } - id = be16toh(id); - if ((id >> 4) != 0x140) { - CPRINTS("FPC unknown silicon 0x%04x", id); - return EC_ERROR_INVAL; - } - CPRINTS("FPC1140 id 0x%04x", id); - - return EC_SUCCESS; -} - -static uint8_t fpc_read_clear_int(void) -{ - const uint8_t cmd = FPC_CMD_INT_CLR; - uint8_t val = 0xff; - - if (spi_transaction(SPI_FPC_DEVICE, &cmd, 1, &val, 1)) - return 0xff; - return val; -} - -static uint8_t fpc_read_int(void) -{ - const uint8_t cmd = FPC_CMD_INT_STS; - uint8_t val = 0xff; - - if (spi_transaction(SPI_FPC_DEVICE, &cmd, 1, &val, 1)) - return 0xff; - return val; -} - -static uint8_t fpc_read_status(void) -{ - const uint8_t cmd = FPC_CMD_STATUS; - uint8_t val[2]; - - if (spi_transaction(SPI_FPC_DEVICE, &cmd, 1, val, 2)) - return 0xff; - return val[1]; -} - -static int fpc_wait_for_idle(void) -{ - uint8_t sts; - int retries = 100; - - do { - fpc_read_clear_int(); - sts = fpc_read_status(); - } while (sts != FPC_IDLE_MASK && retries--); - - return sts != FPC_IDLE_MASK; -} - -/* Reset and initialize the sensor IC */ -static int fpc_init(void) -{ -#ifdef HAVE_PRIVATE - memcpy(&u.sensor_config, &fpc1145_config, fpc1145_config_size); -#endif - /* configure the SPI controller (also ensure that CS_N is high) */ - gpio_config_module(MODULE_SPI_MASTER, 1); - spi_enable(CONFIG_SPI_FP_PORT, 1); - - /* Ensure we pulse reset low to initiate the startup */ - gpio_set_level(GPIO_FP_RST_ODL, 0); - usleep(100); - gpio_set_level(GPIO_FP_RST_ODL, 1); - /* the IRQ line should be set high by the sensor */ - usleep(10000); - if (!gpio_get_level(GPIO_FPS_INT)) { - CPRINTS("FPC not ready"); - return EC_ERROR_TIMEOUT; - } - - /* Check the Hardware ID */ - if (fpc_check_hwid()) - return EC_ERROR_INVAL; - - /* clear the pending 'ready' IRQ before enabling interrupts */ - fpc_read_clear_int(); - gpio_enable_interrupt(GPIO_FPS_INT); - - fpc_send_cmd(FPC_CMD_DEEPSLEEP); - - return EC_SUCCESS; -} - -static void fp_configure_sensor(void) -{ - int i, index; - - for (i = 0, index = 0; i < u.sensor_config.count; i++) { - uint8_t *data = u.sensor_config.data + index; - int len = u.sensor_config.len[i]; - int rc = spi_transaction(&spi_devices[0], data, len, NULL, 0); - - if (rc) - CPRINTS("Config %d failed with %d for 0x%02x", - i, rc, data[0]); - index += len; - } -} - -static void fp_prepare_capture(void) -{ - /* wake it from deep-sleep by doing a soft-reset */ - fpc_send_cmd(FPC_CMD_SOFT_RESET); - fpc_wait_for_idle(); - fp_configure_sensor(); - /* sleep until the finger down is detected */ - fpc_send_cmd(FPC_CMD_SLEEP); -} - -/* Interrupt line from the fingerprint sensor */ -void fps_event(enum gpio_signal signal) -{ - task_wake(TASK_ID_FPC1140); -} - -void fp_task(void) -{ - fpc_init(); - - while (1) { - uint8_t evt; - - task_wait_event(-1); - evt = fpc_read_int(); - atomic_or(&fp_events, evt); - CPRINTS("FPS event %02x", evt); - - if (evt & FPC_INT_FINGER_DOWN) - CPRINTS("Finger!"); - - if (evt) - mkbp_send_event(EC_MKBP_EVENT_FINGERPRINT); - } -} - -static int fp_get_next_event(uint8_t *out) -{ - uint32_t event_out = atomic_read_clear(&fp_events); - - memcpy(out, &event_out, sizeof(event_out)); - - return sizeof(event_out); -} -DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_FINGERPRINT, fp_get_next_event); - -static int fp_command_passthru(struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_passthru *params = args->params; - void *out = args->response; - int rc; - int ret = EC_RES_SUCCESS; - - if (system_is_locked()) - return EC_RES_ACCESS_DENIED; - - if (params->len > args->params_size + - offsetof(struct ec_params_fp_passthru, data) || - params->len > args->response_max) - return EC_RES_INVALID_PARAM; - - rc = spi_transaction_async(&spi_devices[0], params->data, - params->len, out, SPI_READBACK_ALL); - if (params->flags & EC_FP_FLAG_NOT_COMPLETE) - rc |= spi_transaction_wait(&spi_devices[0]); - else - rc |= spi_transaction_flush(&spi_devices[0]); - - if (rc == EC_ERROR_TIMEOUT) - ret = EC_RES_TIMEOUT; - else if (rc) - ret = EC_RES_ERROR; - - args->response_size = params->len; - return ret; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_PASSTHRU, fp_command_passthru, EC_VER_MASK(0)); - -static int fp_command_sensor_config(struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_sensor_config *p = args->params; - int i, index; - unsigned limit = args->params_size - - offsetof(struct ec_params_fp_sensor_config, data); - - /* Validate the content size */ - if (p->count > EC_FP_SENSOR_CONFIG_MAX_REGS || - args->params_size > sizeof(u)) - return EC_RES_INVALID_PARAM; - for (i = 0, index = 0; i < p->count; i++) { - if (index + p->len[i] > limit) - return EC_RES_INVALID_PARAM; - index += p->len[i]; - } - - memcpy(&u.sensor_config, p, args->params_size); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_SENSOR_CONFIG, fp_command_sensor_config, - EC_VER_MASK(0)); - -static int fp_command_mode(struct host_cmd_handler_args *args) -{ - const struct ec_params_fp_mode *p = args->params; - struct ec_response_fp_mode *r = args->response; - - if (!(p->mode & FP_MODE_DONT_CHANGE)) { - sensor_mode = p->mode; - if (p->mode & FP_MODE_DEEPSLEEP) { - fpc_send_cmd(FPC_CMD_DEEPSLEEP); - } else { - if (p->mode & FP_MODE_FINGER_DOWN) - fp_prepare_capture(); - if (p->mode & FP_MODE_FINGER_UP) - /* TBD */; - } - } - - r->mode = sensor_mode; - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_MODE, fp_command_mode, EC_VER_MASK(0)); - -static int fp_command_info(struct host_cmd_handler_args *args) -{ - struct ec_response_fp_info *r = args->response; - int rc; - const uint8_t cmd = FPC_CMD_HW_ID; - uint16_t id; - int ret = EC_RES_SUCCESS; - -#ifdef HAVE_PRIVATE - memcpy(r, &fpc1145_info, sizeof(*r)); -#else - return EC_RES_UNAVAILABLE; -#endif - rc = spi_transaction(SPI_FPC_DEVICE, &cmd, 1, (void *)&id, sizeof(id)); - if (rc) - return EC_RES_ERROR; - r->model_id = be16toh(id); - - args->response_size = sizeof(*r); - return ret; -} -DECLARE_HOST_COMMAND(EC_CMD_FP_INFO, fp_command_info, EC_VER_MASK(0)); - -static int fp_command_frame(struct host_cmd_handler_args *args) -{ -#ifdef HAVE_PRIVATE - const struct ec_params_fp_frame *params = args->params; - void *out = args->response; - - if (params->offset + params->size > sizeof(fp_buffer) || - params->size > args->response_max) - return EC_RES_INVALID_PARAM; - - memcpy(out, fp_buffer + params->offset, params->size); - - args->response_size = params->size; - return EC_RES_SUCCESS; -#else - return EC_RES_UNAVAILABLE; -#endif -} -DECLARE_HOST_COMMAND(EC_CMD_FP_FRAME, fp_command_frame, EC_VER_MASK(0)); |