Files
kernel_samsung_sdm670/drivers/fingerprint/gf_platform.c
Bruno Martins dbcc8fefd9 treewide: Import Samsung changes from T725XXU2DUD1
Change-Id: I5c31dc4a8006a967910963fb9e7d1a0ab4ab9731
2022-02-23 22:14:25 +01:00

471 lines
11 KiB
C

#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/timer.h>
#include <linux/err.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>
#include "gf_common.h"
void gfspi_spi_setup_conf(struct gf_device *gf_dev, u32 speed)
{
u32 max_speed_hz;
switch (speed) {
case 1:
case 4:
case 6:
case 8:
default:
max_speed_hz = MAX_BAUD_RATE;
break;
}
gf_dev->spi->mode = SPI_MODE_0;
gf_dev->spi->max_speed_hz = max_speed_hz;
gf_dev->spi->bits_per_word = 8;
gf_dev->current_spi_speed = max_speed_hz;
#ifndef ENABLE_SENSORS_FPRINT_SECURE
if (spi_setup(gf_dev->spi))
pr_err("%s, failed to setup spi conf\n", __func__);
#endif
}
#ifndef ENABLE_SENSORS_FPRINT_SECURE
int gfspi_spi_read_bytes(struct gf_device *gf_dev, u16 addr,
u32 data_len, u8 *rx_buf)
{
struct spi_message msg;
struct spi_transfer *xfer = NULL;
u8 *tmp_buf = NULL;
xfer = kzalloc(sizeof(*xfer) * 2, GFP_KERNEL);
if (xfer == NULL)
return -ENOMEM;
tmp_buf = gf_dev->spi_buffer;
spi_message_init(&msg);
*tmp_buf = 0xF0;
*(tmp_buf + 1) = (u8)((addr >> 8) & 0xFF);
*(tmp_buf + 2) = (u8)(addr & 0xFF);
xfer[0].tx_buf = tmp_buf;
xfer[0].len = 3;
xfer[0].delay_usecs = 5;
spi_message_add_tail(&xfer[0], &msg);
spi_sync(gf_dev->spi, &msg);
spi_message_init(&msg);
/* memset((tmp_buf + 4), 0x00, data_len + 1); */
/* 4 bytes align */
*(tmp_buf + 4) = 0xF1;
xfer[1].tx_buf = tmp_buf + 4;
xfer[1].rx_buf = tmp_buf + 4;
xfer[1].len = data_len + 1;
xfer[1].delay_usecs = 5;
spi_message_add_tail(&xfer[1], &msg);
spi_sync(gf_dev->spi, &msg);
memcpy(rx_buf, (tmp_buf + 5), data_len);
kfree(xfer);
if (xfer != NULL)
xfer = NULL;
return 0;
}
int gfspi_spi_write_bytes(struct gf_device *gf_dev, u16 addr,
u32 data_len, u8 *tx_buf)
{
struct spi_message msg;
struct spi_transfer *xfer = NULL;
u8 *tmp_buf = NULL;
xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
if (xfer == NULL)
return -ENOMEM;
tmp_buf = gf_dev->spi_buffer;
spi_message_init(&msg);
*tmp_buf = 0xF0;
*(tmp_buf + 1) = (u8)((addr >> 8) & 0xFF);
*(tmp_buf + 2) = (u8)(addr & 0xFF);
memcpy(tmp_buf + 3, tx_buf, data_len);
xfer[0].len = data_len + 3;
xfer[0].tx_buf = tmp_buf;
xfer[0].delay_usecs = 5;
spi_message_add_tail(&xfer[0], &msg);
spi_sync(gf_dev->spi, &msg);
kfree(xfer);
if (xfer != NULL)
xfer = NULL;
return 0;
}
int gfspi_spi_read_byte(struct gf_device *gf_dev, u16 addr, u8 *value)
{
struct spi_message msg;
struct spi_transfer *xfer = NULL;
xfer = kzalloc(sizeof(*xfer) * 2, GFP_KERNEL);
if (xfer == NULL)
return -ENOMEM;
spi_message_init(&msg);
*gf_dev->spi_buffer = 0xF0;
*(gf_dev->spi_buffer + 1) = (u8)((addr >> 8) & 0xFF);
*(gf_dev->spi_buffer + 2) = (u8)(addr & 0xFF);
xfer[0].tx_buf = gf_dev->spi_buffer;
xfer[0].len = 3;
xfer[0].delay_usecs = 5;
spi_message_add_tail(&xfer[0], &msg);
spi_sync(gf_dev->spi, &msg);
spi_message_init(&msg);
/* 4 bytes align */
*(gf_dev->spi_buffer + 4) = 0xF1;
xfer[1].tx_buf = gf_dev->spi_buffer + 4;
xfer[1].rx_buf = gf_dev->spi_buffer + 4;
xfer[1].len = 2;
xfer[1].delay_usecs = 5;
spi_message_add_tail(&xfer[1], &msg);
spi_sync(gf_dev->spi, &msg);
*value = *(gf_dev->spi_buffer + 5);
kfree(xfer);
if (xfer != NULL)
xfer = NULL;
return 0;
}
int gfspi_spi_write_byte(struct gf_device *gf_dev, u16 addr, u8 value)
{
struct spi_message msg;
struct spi_transfer *xfer = NULL;
xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
if (xfer == NULL)
return -ENOMEM;
spi_message_init(&msg);
*gf_dev->spi_buffer = 0xF0;
*(gf_dev->spi_buffer + 1) = (u8)((addr >> 8) & 0xFF);
*(gf_dev->spi_buffer + 2) = (u8)(addr & 0xFF);
*(gf_dev->spi_buffer + 3) = value;
xfer[0].tx_buf = gf_dev->spi_buffer;
xfer[0].len = 3 + 1;
xfer[0].delay_usecs = 5;
spi_message_add_tail(&xfer[0], &msg);
spi_sync(gf_dev->spi, &msg);
kfree(xfer);
if (xfer != NULL)
xfer = NULL;
return 0;
}
static int gfspi_spi_transfer_raw(struct gf_device *gf_dev, u8 *tx_buf,
u8 *rx_buf, u32 len)
{
struct spi_message msg;
struct spi_transfer xfer;
spi_message_init(&msg);
memset(&xfer, 0, sizeof(struct spi_transfer));
xfer.tx_buf = tx_buf;
xfer.rx_buf = rx_buf;
xfer.len = len;
spi_message_add_tail(&xfer, &msg);
spi_sync(gf_dev->spi, &msg);
return 0;
}
int gfspi_ioctl_transfer_raw_cmd(struct gf_device *gf_dev,
unsigned long arg, unsigned int bufsiz)
{
struct gf_ioc_transfer_raw ioc_xraw;
int retval = 0;
#ifdef CONFIG_SENSORS_FINGERPRINT_32BITS_PLATFORM_ONLY
struct gf_ioc_transfer_raw_32 ioc_xraw_32;
u64 read_buf_64;
u64 write_buf_64;
#endif
do {
u8 *tx_buf;
u8 *rx_buf;
uint32_t len;
#ifdef CONFIG_SENSORS_FINGERPRINT_32BITS_PLATFORM_ONLY
if (copy_from_user(&ioc_xraw_32, (void __user *)arg,
sizeof(struct gf_ioc_transfer_raw_32)))
#else
if (copy_from_user(&ioc_xraw, (void __user *)arg,
sizeof(struct gf_ioc_transfer_raw)))
#endif
{
pr_err("%s: Failed to copy gf_ioc_transfer_raw from user to kernel\n",
__func__);
retval = -EFAULT;
break;
}
#ifdef CONFIG_SENSORS_FINGERPRINT_32BITS_PLATFORM_ONLY
read_buf_64 = (u64)ioc_xraw_32.read_buf;
write_buf_64 = (u64)ioc_xraw_32.write_buf;
ioc_xraw.read_buf = (u8 *)read_buf_64;
ioc_xraw.write_buf = (u8 *)write_buf_64;
ioc_xraw.high_time = ioc_xraw_32.high_time;
ioc_xraw.len = ioc_xraw_32.len;
ioc_xraw.low_time = ioc_xraw_32.low_time;
#endif
if ((ioc_xraw.len > bufsiz) || (ioc_xraw.len == 0)) {
pr_err("%s: request transfer length larger than maximum buffer\n",
__func__);
pr_err("%s: buf max %x, buf_len %x\n", __func__, bufsiz, ioc_xraw.len);
retval = -EINVAL;
break;
}
if (ioc_xraw.read_buf == NULL || ioc_xraw.write_buf == NULL) {
pr_err("%s: read buf and write buf can not equal to NULL simultaneously.\n",
__func__);
retval = -EINVAL;
break;
}
/* change speed and set transfer mode */
gfspi_spi_setup_conf(gf_dev, ioc_xraw.high_time);
len = ioc_xraw.len;
tx_buf = kzalloc(len, GFP_KERNEL);
if (tx_buf == NULL) {
pr_err("%s: failed to allocate tx buffer\n",
__func__);
retval = -EMSGSIZE;
break;
}
rx_buf = kzalloc(len, GFP_KERNEL);
if (rx_buf == NULL) {
kfree(tx_buf);
pr_err("%s: failed to allocate rx buffer\n",
__func__);
retval = -EMSGSIZE;
break;
}
if (copy_from_user(tx_buf, (void __user *)ioc_xraw.write_buf,
ioc_xraw.len)) {
kfree(tx_buf);
kfree(rx_buf);
pr_err("Failed to copy gf_ioc_transfer from user to kernel\n");
retval = -EFAULT;
break;
}
gfspi_spi_transfer_raw(gf_dev, tx_buf, rx_buf, len);
if (copy_to_user((void __user *)ioc_xraw.read_buf,
rx_buf, ioc_xraw.len)) {
pr_err("Failed to copy gf_ioc_transfer_raw from kernel to user\n");
retval = -EFAULT;
}
kfree(tx_buf);
kfree(rx_buf);
} while (0);
return retval;
}
int gfspi_ioctl_spi_init_cfg_cmd(struct gf_device *gf_dev, unsigned long arg)
{
return 0;
}
#endif
/*GPIO pins reference.*/
int gfspi_get_gpio_dts_info(struct device *dev, struct gf_device *gf_dev)
{
struct device_node *np = dev->of_node;
int status = 0;
/*get pwr resource*/
gf_dev->pwr_gpio = of_get_named_gpio(np, "goodix,gpio_pwr", 0);
if (!gpio_is_valid(gf_dev->pwr_gpio)) {
pr_err("%s, PWR GPIO is invalid.\n", __func__);
return -1;
}
pr_info("%s, goodix_pwr:%d\n", __func__, gf_dev->pwr_gpio);
status = gpio_request(gf_dev->pwr_gpio, "goodix_pwr");
if (status < 0) {
pr_err("%s, Failed to request PWR GPIO. rc = %d\n",
__func__, status);
return status;
}
gpio_direction_output(gf_dev->pwr_gpio, 0);
/*get reset resource*/
gf_dev->reset_gpio = of_get_named_gpio(np, "goodix,gpio_reset", 0);
if (!gpio_is_valid(gf_dev->reset_gpio)) {
pr_err("%s, RESET GPIO is invalid.\n", __func__);
return -1;
}
pr_info("%s, goodix_reset:%d\n",
__func__, gf_dev->reset_gpio);
status = gpio_request(gf_dev->reset_gpio, "goodix_reset");
if (status < 0) {
pr_err("%s, Failed to request RESET GPIO. rc = %d\n",
__func__, status);
return status;
}
gpio_direction_output(gf_dev->reset_gpio, 0);
/*get irq resourece*/
gf_dev->irq_gpio = of_get_named_gpio(np, "goodix,gpio_irq", 0);
if (!gpio_is_valid(gf_dev->irq_gpio)) {
pr_err("%s, IRQ GPIO is invalid.\n", __func__);
return -1;
}
pr_info("%s, irq_gpio:%d\n", __func__, gf_dev->irq_gpio);
status = gpio_request(gf_dev->irq_gpio, "goodix_irq");
if (status < 0) {
pr_err("%s, Failed to request IRQ GPIO. rc = %d\n",
__func__, status);
return status;
}
gpio_direction_input(gf_dev->irq_gpio);
if (of_property_read_u32(np, "goodix,min_cpufreq_limit",
&gf_dev->min_cpufreq_limit))
gf_dev->min_cpufreq_limit = 0;
if (of_property_read_string_index(np, "goodix,chip_id", 0,
(const char **)&gf_dev->chipid))
gf_dev->chipid = "NULL";
pr_info("%s, Chip ID:%s\n", __func__, gf_dev->chipid);
gf_dev->p = pinctrl_get_select(dev, "default");
if (IS_ERR(gf_dev->p)) {
status = -EINVAL;
pr_err("%s: failed pinctrl_get\n", __func__);
goto fail_pinctrl_get;
}
gf_dev->pins_sleep = pinctrl_lookup_state(gf_dev->p, "sleep");
if (IS_ERR(gf_dev->pins_sleep)) {
pr_err("%s : could not get pins sleep_state (%li)\n",
__func__, PTR_ERR(gf_dev->pins_sleep));
status = -EINVAL;
goto fail_pinctrl_get;
}
gf_dev->pins_idle = pinctrl_lookup_state(gf_dev->p, "idle");
if (IS_ERR(gf_dev->pins_idle)) {
pr_err("%s : could not get pins idle_state (%li)\n",
__func__, PTR_ERR(gf_dev->pins_idle));
goto fail_pinctrl_get;
}
gfspi_pin_control(gf_dev, false);
if (of_property_read_u32(np, "goodix,orient", &gf_dev->orient))
gf_dev->orient = 0;
pr_info("%s: orient=%d\n", __func__, gf_dev->orient);
fail_pinctrl_get:
pinctrl_put(gf_dev->p);
return status;
}
void gfspi_cleanup_info(struct gf_device *gf_dev)
{
if (gpio_is_valid(gf_dev->irq_gpio)) {
gpio_free(gf_dev->irq_gpio);
pr_debug("%s, remove irq_gpio.\n", __func__);
}
if (gpio_is_valid(gf_dev->reset_gpio)) {
gpio_free(gf_dev->reset_gpio);
pr_debug("%s, remove reset_gpio.\n", __func__);
}
if (gpio_is_valid(gf_dev->pwr_gpio)) {
gpio_free(gf_dev->pwr_gpio);
pr_debug("%s, remove pwr_gpio.\n", __func__);
}
}
int gfspi_spi_clk_enable(struct gf_device *gf_dev)
{
int ret_val = 0;
#ifdef ENABLE_SENSORS_FPRINT_SECURE
if (gf_dev->enabled_clk) {
pr_info("%s already enabled same clock.\n",
__func__);
return ret_val;
}
pr_info("%s ENABLE_SPI_CLOCK %ld\n",
__func__, (long int)gf_dev->spi->max_speed_hz);
wake_lock(&gf_dev->wake_lock);
gf_dev->enabled_clk = true;
#endif
return ret_val;
}
int gfspi_spi_clk_disable(struct gf_device *gf_dev)
{
int ret_val = 0;
#ifdef ENABLE_SENSORS_FPRINT_SECURE
if (gf_dev->enabled_clk) {
pr_info("%s DISABLE_SPI_CLOCK\n", __func__);
wake_unlock(&gf_dev->wake_lock);
gf_dev->enabled_clk = false;
pr_info("%s, clk disalbed\n", __func__);
}
#endif
return ret_val;
}
int gfspi_pin_control(struct gf_device *gf_dev, bool pin_set)
{
int status = 0;
if (pin_set) {
if (!IS_ERR(gf_dev->pins_idle)) {
status = pinctrl_select_state(gf_dev->p,
gf_dev->pins_idle);
if (status)
pr_err("%s: can't set pin default state\n",
__func__);
pr_debug("%s idle\n", __func__);
}
} else {
if (!IS_ERR(gf_dev->pins_sleep)) {
status = pinctrl_select_state(gf_dev->p,
gf_dev->pins_sleep);
if (status)
pr_err("%s: can't set pin sleep state\n",
__func__);
pr_debug("%s sleep\n", __func__);
}
}
return status;
}