/* 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 #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; }