496 lines
14 KiB
C
Executable file
496 lines
14 KiB
C
Executable file
/* Copyright (C) MicroArray
|
|
* MicroArray Fprint Driver Code
|
|
* mtk-settings.c
|
|
* Date: 2017-3-15
|
|
* Version: v4.0.06
|
|
* Author: guq
|
|
* Contact: guq@microarray.com.cn
|
|
*/
|
|
|
|
#include "mtk-settings.h"
|
|
|
|
|
|
|
|
#ifdef TEE_ID_COMPATIBLE_TRUSTKERNEL
|
|
#include <linux/tee_fp.h>
|
|
#endif
|
|
static int ret;
|
|
//pin control sturct data, define using for the dts settings,
|
|
struct pinctrl *mas_finger_pinctrl;
|
|
struct pinctrl_state //*mas_finger_power2v8_on, *mas_finger_power2v8_off, //power2v8
|
|
//*mas_finger_power1v8_on, *mas_finger_power1v8_off, //power1v8
|
|
*mas_finger_rst_on, *mas_finger_rst_off, //rst
|
|
*mas_finger_eint_on, *mas_finger_eint_off, //eint
|
|
*mas_spi_ck_on, //for ck
|
|
*mas_spi_cs_on, //for cs
|
|
*mas_spi_mi_on, *mas_spi_mi_off, //for mi
|
|
*mas_spi_mo_on, *mas_spi_mo_off, //for mo
|
|
*mas_spi_default; //same odms only use default to setting the dts
|
|
static struct device_node *node;
|
|
|
|
static unsigned int finger_int_pin;
|
|
|
|
/**
|
|
* the platform struct start,for getting the platform device to set gpio state
|
|
*/
|
|
//#ifdef CONFIG_OF
|
|
static struct of_device_id sof_match[] = {
|
|
{ .compatible = MA_DTS_NAME, },
|
|
{},
|
|
};
|
|
static struct of_device_id sof_dev_match[] = {
|
|
{ .compatible = "prize,mas_fingerprint", },
|
|
{},
|
|
};
|
|
MODULE_DEVICE_TABLE(of, sof_match);
|
|
MODULE_DEVICE_TABLE(of, sof_dev_match);
|
|
//#endif
|
|
static struct platform_driver spdrv = {
|
|
.probe = mas_plat_probe,
|
|
.remove = mas_plat_remove,
|
|
.driver = {
|
|
.name = MA_DRV_NAME,
|
|
.owner = THIS_MODULE,
|
|
#ifdef CONFIG_OF
|
|
.of_match_table = sof_match,
|
|
//.of_match_table = of_match_ptr(sof_match),
|
|
#endif
|
|
}
|
|
};
|
|
/**
|
|
* the platform struct start,for getting the platform device to set gpio state end
|
|
*/
|
|
|
|
|
|
/**
|
|
* the spi struct date start,for getting the spi_device to set the spi clock enable start
|
|
*/
|
|
|
|
struct spi_device_id sdev_id = {MA_DRV_NAME, 0};
|
|
struct spi_driver sdrv = {
|
|
.driver = {
|
|
.name = MA_DRV_NAME,
|
|
.bus = &spi_bus_type,
|
|
.owner = THIS_MODULE,
|
|
#ifdef CONFIG_OF
|
|
.of_match_table = sof_dev_match,
|
|
#endif
|
|
},
|
|
.probe = mas_probe,
|
|
.remove = mas_remove,
|
|
// .id_table = &sdev_id,
|
|
};
|
|
//driver end
|
|
#ifndef CONFIG_OF
|
|
static struct mt_chip_conf smt_conf = {
|
|
.setuptime=15,
|
|
.holdtime=15,
|
|
.high_time=15, // 10--6m 15--4m 20--3m 30--2m [ 60--1m 120--0.5m 300--0.2m]
|
|
.low_time=15,
|
|
.cs_idletime=15,
|
|
.ulthgh_thrsh=0,
|
|
.cpol=0,
|
|
.cpha=0,
|
|
.rx_mlsb=SPI_MSB,
|
|
.tx_mlsb=SPI_MSB,
|
|
.tx_endian=0,
|
|
.rx_endian=0,
|
|
.com_mod=FIFO_TRANSFER,
|
|
.pause=0,
|
|
.finish_intr=5,
|
|
.deassert=0,
|
|
.ulthigh=0,
|
|
.tckdly=0,
|
|
};
|
|
|
|
struct spi_board_info smt_info[] __initdata = {
|
|
[0] = {
|
|
.modalias = MA_DRV_NAME,
|
|
.max_speed_hz = (4*1000000),
|
|
.bus_num = 0,
|
|
.chip_select = 0,
|
|
.mode = SPI_MODE_0,
|
|
.controller_data = &smt_conf,
|
|
},
|
|
};
|
|
//device end
|
|
|
|
void mas_set_spi_controller_data(struct spi_device *spi)
|
|
{
|
|
spi->mode = SPI_MODE_0;
|
|
spi->bits_per_word = 8;
|
|
spi->max_speed_hz = SPI_SPEED;
|
|
spi->controller_data = (void *)&smt_conf ;
|
|
spi_setup(spi);
|
|
}
|
|
|
|
/**
|
|
* the spi struct date start,for getting the spi_device to set the spi clock enable end
|
|
*/
|
|
|
|
|
|
void mas_select_transfer(struct spi_device *spi, int len) {
|
|
static int mode = -1;
|
|
int tmp = len>32? DMA_TRANSFER: FIFO_TRANSFER;
|
|
struct mt_chip_conf *conf = &smt_conf;
|
|
if(tmp!=mode) {
|
|
conf = (struct mt_chip_conf *) spi->controller_data;
|
|
conf->com_mod = tmp;
|
|
spi_setup(spi);
|
|
mode = tmp;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* set spi speed, often we must check whether the setting is efficient
|
|
*/
|
|
|
|
void ma_spi_change(struct spi_device *spi, unsigned int speed, int flag)
|
|
{
|
|
struct mt_chip_conf *mcc = (struct mt_chip_conf *)spi->controller_data;
|
|
if(flag == 0) {
|
|
mcc->com_mod = FIFO_TRANSFER;
|
|
} else {
|
|
mcc->com_mod = DMA_TRANSFER;
|
|
}
|
|
mcc->high_time = speed;
|
|
mcc->low_time = speed;
|
|
if(spi_setup(spi) < 0){
|
|
MALOGE("change the spi error!\n");
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
int mas_do_some_for_probe(struct spi_device *spi){
|
|
return 0;
|
|
}
|
|
|
|
|
|
int __init mas_get_platform(void) {
|
|
MALOGD("start!");
|
|
|
|
ret = platform_driver_register(&spdrv);
|
|
if(ret){
|
|
printk("===wys===mas_get_platform= driver_register==error=\n");
|
|
return ret;
|
|
}
|
|
/*MALOGD("start board info");
|
|
ret = spi_register_board_info(smt_info, ARRAY_SIZE(smt_info));
|
|
if(ret){
|
|
MALOGE("spi_register_board_info");
|
|
}*/
|
|
|
|
MALOGD("start register spi");
|
|
ret = spi_register_driver(&sdrv);
|
|
if(ret) {
|
|
printk("==wys==spi_register_driver===error===\n");
|
|
return ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int mas_remove_platform(void){
|
|
spi_unregister_driver(&sdrv);
|
|
platform_driver_unregister(&spdrv);
|
|
return 0;
|
|
}
|
|
|
|
int mas_finger_get_gpio_info(struct platform_device *pdev){
|
|
MALOGD("start!");
|
|
node = of_find_compatible_node(NULL, NULL, MA_DTS_NAME);
|
|
//pdev = of_find_device_by_node(node);
|
|
mas_finger_pinctrl = devm_pinctrl_get(&pdev->dev);
|
|
if (IS_ERR(mas_finger_pinctrl)) {
|
|
ret = PTR_ERR(mas_finger_pinctrl);
|
|
dev_err(&pdev->dev, "mas_finger_pinctrl cannot find pinctrl\n");
|
|
return ret;
|
|
}
|
|
|
|
|
|
mas_spi_mi_on = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_mode_as_mi");
|
|
if (IS_ERR(mas_spi_mi_on)) {
|
|
ret = PTR_ERR(mas_spi_mi_on);
|
|
dev_err(&pdev->dev, " Cannot find mas_spi_mi_on pinctrl!\n");
|
|
return ret;
|
|
}
|
|
mas_spi_mi_off = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_miso_pull_down");
|
|
if (IS_ERR(mas_spi_mi_off)) {
|
|
ret = PTR_ERR(mas_spi_mi_off);
|
|
dev_err(&pdev->dev, " Cannot find mas_spi_mi_off pinctrl!\n");
|
|
return ret;
|
|
}
|
|
mas_spi_mo_on = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_mode_as_mo");
|
|
if (IS_ERR(mas_spi_mo_on)) {
|
|
ret = PTR_ERR(mas_spi_mo_on);
|
|
dev_err(&pdev->dev, " Cannot find mas_spi_mo_on pinctrl!\n");
|
|
return ret;
|
|
}
|
|
|
|
mas_spi_mo_off = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_mosi_pull_down");
|
|
if (IS_ERR(mas_spi_mo_off)) {
|
|
ret = PTR_ERR(mas_spi_mo_off);
|
|
dev_err(&pdev->dev, " Cannot find mas_spi_mo_off!\n");
|
|
return ret;
|
|
}
|
|
|
|
mas_spi_ck_on = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_mode_as_ck");
|
|
if (IS_ERR(mas_spi_ck_on)) {
|
|
ret = PTR_ERR(mas_spi_ck_on);
|
|
dev_err(&pdev->dev, " Cannot find mas_spi_ck_on pinctrl!\n");
|
|
return ret;
|
|
}
|
|
|
|
// mas_spi_ck_off = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_pins_clk_as_gpio");
|
|
// if (IS_ERR(mas_spi_ck_off)) {
|
|
// ret = PTR_ERR(mas_spi_ck_off);
|
|
// dev_err(&pdev->dev, " Cannot find mas_spi_ck_off pinctrl !\n");
|
|
// return ret;
|
|
// }
|
|
|
|
mas_spi_cs_on = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_mode_as_cs");
|
|
if (IS_ERR(mas_spi_cs_on)) {
|
|
ret = PTR_ERR(mas_spi_cs_on);
|
|
dev_err(&pdev->dev, " Cannot find mas_spi_cs_on pinctrl!\n");
|
|
return ret;
|
|
}
|
|
|
|
// mas_spi_cs_off = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_pins_cs_low");
|
|
// if (IS_ERR(mas_spi_cs_off)) {
|
|
// ret = PTR_ERR(mas_spi_cs_off);
|
|
// dev_err(&pdev->dev, " Cannot find mas_spi_cs_off pinctrl!\n");
|
|
// return ret;
|
|
// }
|
|
|
|
mas_finger_rst_on = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_pins_rst_high");
|
|
if (IS_ERR(mas_finger_rst_on)) {
|
|
ret = PTR_ERR(mas_finger_rst_on);
|
|
dev_err(&pdev->dev, " Cannot find mas_finger_rst_on pinctrl!\n");
|
|
return ret;
|
|
}
|
|
|
|
mas_finger_rst_off = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_pins_rst_low");
|
|
if (IS_ERR(mas_finger_rst_off)) {
|
|
ret = PTR_ERR(mas_finger_rst_off);
|
|
dev_err(&pdev->dev, " Cannot find mas_finger_rst_off pinctrl!\n");
|
|
return ret;
|
|
}
|
|
|
|
|
|
mas_finger_eint_on = pinctrl_lookup_state(mas_finger_pinctrl, "fpc_eint_as_int");
|
|
if (IS_ERR(mas_finger_eint_on)) {
|
|
ret = PTR_ERR(mas_finger_eint_on);
|
|
dev_err(&pdev->dev, " Cannot find mas_finger_eint_on pinctrl!\n");
|
|
return ret;
|
|
}
|
|
|
|
MALOGD("end!");
|
|
return 0;
|
|
}
|
|
|
|
void mas_free_dts_info(void)
|
|
{
|
|
if(mas_finger_pinctrl != NULL) devm_pinctrl_put(mas_finger_pinctrl);
|
|
}
|
|
|
|
int mas_finger_set_spi(int cmd){
|
|
//#if 0
|
|
switch(cmd)
|
|
{
|
|
case 0:
|
|
// if( (!IS_ERR(mas_spi_cs_off)) && (!IS_ERR(mas_spi_ck_off)) && (!IS_ERR(mas_spi_mi_off)) && (!IS_ERR(mas_spi_mo_off)) ){
|
|
if( (!IS_ERR(mas_spi_mi_off)) && (!IS_ERR(mas_spi_mo_off)) ){
|
|
// pinctrl_select_state(mas_finger_pinctrl, mas_spi_cs_off);
|
|
// pinctrl_select_state(mas_finger_pinctrl, mas_spi_ck_off);
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_spi_mi_off);
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_spi_mo_off);
|
|
MALOGE("mas_spi_gpio_slect_pinctrl cmd=0 ok!");
|
|
}else{
|
|
MALOGE("mas_spi_gpio_slect_pinctrl cmd=0 err!");
|
|
return -1;
|
|
}
|
|
break;
|
|
case 1:
|
|
if( (!IS_ERR(mas_spi_cs_on)) && (!IS_ERR(mas_spi_ck_on)) && (!IS_ERR(mas_spi_mi_on)) && (!IS_ERR(mas_spi_mo_on)) ){
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_spi_cs_on);
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_spi_ck_on);
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_spi_mi_on);
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_spi_mo_on);
|
|
MALOGE("mas_spi_gpio_slect_pinctrl cmd=1 ok!");
|
|
}else{
|
|
MALOGE("mas_spi_gpio_slect_pinctrl cmd=1 err!");
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
//#endif
|
|
return 0;
|
|
}
|
|
void mas_finger_set_reset(int enable)
|
|
{
|
|
if(enable){
|
|
printk("microarray pri ,reset set 1 \n");
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_rst_on);
|
|
msleep(10);
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_rst_off);
|
|
msleep(20);
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_rst_on);
|
|
}else{
|
|
printk("microarray pri ,reset set 0 \n");
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_rst_off);
|
|
}
|
|
}
|
|
void mas_finger_reset(int enable)
|
|
{
|
|
if(enable){
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_rst_on);
|
|
msleep(10);
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_rst_off);
|
|
msleep(20);
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_rst_on);
|
|
}else{
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_rst_off);
|
|
}
|
|
}
|
|
|
|
int mas_finger_set_power(int cmd)
|
|
{
|
|
int ret = 0;
|
|
if(cmd){
|
|
printk("microarray pri ,power set 1 \n");
|
|
#if defined(CONFIG_PRIZE_FP_USE_VFP)
|
|
ret = vfp_regulator_ctl(1);
|
|
|
|
#endif
|
|
mas_finger_set_reset(1);
|
|
}else{
|
|
printk("microarray pri ,power set 0 \n");
|
|
#if defined(CONFIG_PRIZE_FP_USE_VFP)
|
|
ret = vfp_regulator_ctl(0);
|
|
|
|
#endif
|
|
mas_finger_set_reset(0);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* this is a demo function,if the power on-off switch by other way
|
|
* modify it as the right way
|
|
* on_off 1 on 0 off
|
|
*/
|
|
int mas_switch_power(unsigned int on_off){
|
|
mas_finger_set_power(on_off); //use this fuction directly if the dts way
|
|
return 0;
|
|
}
|
|
|
|
int mas_finger_set_eint(int cmd)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case 0 :
|
|
if(!IS_ERR(mas_finger_eint_off)){
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_eint_off);
|
|
}else{
|
|
MALOGE("mas_eint_gpio_slect_pinctrl cmd=0 err!");
|
|
return -1;
|
|
}
|
|
break;
|
|
case 1 :
|
|
if(!IS_ERR(mas_finger_eint_on)){
|
|
pinctrl_select_state(mas_finger_pinctrl, mas_finger_eint_on);
|
|
}else{
|
|
MALOGE("mas_eint_gpio_slect_pinctrl cmd=1 err!");
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int mas_finger_set_gpio_info(int cmd){
|
|
ret = 0;
|
|
MALOGD("start!");
|
|
ret |= mas_finger_set_spi(cmd);
|
|
ret |= mas_finger_set_power(cmd);
|
|
// ret |= mas_finger_set_eint(cmd);
|
|
MALOGD("end!");
|
|
return ret;
|
|
}
|
|
|
|
void mas_enable_spi_clock(struct spi_device *spi){
|
|
|
|
#if defined(TEE_ID_COMPATIBLE_TRUSTKERNEL) || defined(TEE_ID_COMPATIBLE_MICROTRUST)
|
|
#ifdef CONFIG_MTK_CLKMGR
|
|
enable_clock(MT_CG_PERI_SPI0, "spi");
|
|
#elif defined(MT6797)
|
|
mt_spi_enable_clk(spi_master_get_devdata(spi->master));
|
|
#else
|
|
mt_spi_enable_master_clk(spi);
|
|
//enable_clk();
|
|
#endif
|
|
#endif
|
|
|
|
}
|
|
|
|
void mas_disable_spi_clock(struct spi_device *spi){
|
|
|
|
#if defined(TEE_ID_COMPATIBLE_TRUSTKERNEL) || defined(TEE_ID_COMPATIBLE_MICROTRUST)
|
|
#ifdef CONFIG_MTK_CLKMGR
|
|
disable_clock(MT_CG_PERI_SPI0, "spi");
|
|
#elif defined(MT6797)
|
|
mt_spi_disable_clk(spi_master_get_devdata(spi->master));
|
|
#else
|
|
mt_spi_disable_master_clk(spi);
|
|
//disable_clk();
|
|
#endif
|
|
#endif
|
|
|
|
}
|
|
|
|
int mas_tee_spi_transfer(u8 *txb, u8 *rxb, int len) {
|
|
int val;
|
|
val = 0;
|
|
|
|
#ifdef TEE_ID_COMPATIBLE_TRUSTKERNEL
|
|
val = tee_spi_transfer(&smt_conf,sizeof(struct mt_chip_conf),txb, rxb, 4);
|
|
#endif
|
|
|
|
return val;
|
|
}
|
|
|
|
unsigned int mas_get_irq(struct device *dev){
|
|
int irq_num;
|
|
finger_int_pin = of_get_named_gpio_flags(dev->of_node,
|
|
"fingerprint,touch-int-gpio", 0, NULL);
|
|
if (!gpio_is_valid(finger_int_pin)){
|
|
MALOGE("invalid irq gpio!");
|
|
return -EINVAL;
|
|
}
|
|
gpio_direction_input(finger_int_pin);
|
|
irq_num = gpio_to_irq(finger_int_pin);
|
|
return irq_num;
|
|
|
|
}
|
|
|
|
/*
|
|
* this function used for check the interrupt gpio state
|
|
* @index 0 gpio level 1 gpio mode, often use 0
|
|
* @return 0 gpio low 1 gpio high if index = 1,the return is the gpio mode
|
|
* under 0 the of_property_read_u32_index return errno,check the dts as below:
|
|
* last but not least use this function must checkt the label on dts file, after is an example:
|
|
* ma_finger: ma_finger{
|
|
* compatible = "mediatek,afs120x";
|
|
* finger_int_pin = <100 0>;
|
|
* }
|
|
*/
|
|
int mas_get_interrupt_gpio(unsigned int index){
|
|
int val;
|
|
val = __gpio_get_value(finger_int_pin);
|
|
//printk if need
|
|
return val;
|
|
}
|
|
|