/fs/debugfs/

rel='vcs-git' href='or' title='litmus-rt-ext-res.git Git repository'/>
aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/input/mouse/cyapa_gen5.c
blob: 5775d40b3d53994a754bd0f5a159adafbea65c3e (plain) (tree)
1
2
3
4
5
6




                                          
                                                      












                                                                             
                          
                            
                             


                  
                                 















                                                                                












                                                                        




                                            
















                                                         
 



                                  
 


                                               

                                    


                                            







                                                 


                                                             









                                                 






                                                      













                                                 
                                                                    


                                                 
 
                               



                                          


                                                                   




























                                                                               



                                                                               


                                                                       
            





































                                                                         


                                                        

           






                                                           





                         















                                                                         
                            




                                                                            
                          



                                                 
                        




                                                                          
                                                



                                                                  
                                 





                                                                     
                                   
                    
                            











                                                              
                              




                            
                         












                                                                              
                                                          









                                    





                                      



                                                                      
 
                                                            

                                 


                                                                              
                                                       
 
                                                                  
 


                                         
 


                                          



                                               







                                                              
                                                                     












                                                        





                                                     
                                                                      













                                                        































                                                                      



                                                                          
                                                    

                                                
                                               
                                                                  
                                                                     






























                                                                                

                                                                 


                                     

                                                            






                                                                               
                                                      
                                                     
                                                                      
                                                              
                                                                    






                                                              
                                                                          




                                     

                                                            

                                                    
                                                              
                                                      
                                                            


                                                      





                                                                               












                                         
                                                                  


                                                        
                                         
 
                                     

                                                         
                                             



                                                                  
                                                              

                                                           
                                             












                                             
                                                                  



                   
                                     

                                                         
                                             



















                                                                   
                                     


                     
                               






                                             
                                                                  





                                          
                                                         


                             


                                   
 

                                                          
                                         


                                                         
                                        
                                              



                                                                             
                                        














                                                                           
                                         



                                                                         



                                               
 
                                     


                     
                                                         

                                  
                                                  


                                            


                                                                          




                            
                                                          

                                  
                                                                  

                     
                                                   

                             





                                                                              

                                                      

                                                                             







                                                               
                                                                       

                                 
                                                      











                                                                            
                                                                    





                                   
                                           

                             
                                                                    
                                                      

                                                                             


                                                                              

                                                             








                                                                               
                                                               

                                 




                                                        





                                                     
                                              
















                                                                


                                                                        






                                                                     
                                                 
                                                         
                                                          

                                                   
                                                                    




                                            
                                                                    
                                                                    



                                                                  


                                                                      



                                                                  



















                                                                               
                                                                    





                                                               

                                                 
                                            
                                                                        
                                                            


                                                          













                                                                       

                                                               



                                                                      


                                                                















                                                                           




                                                                       

                                       
                               
                                         


                                                         

                                       

                                                    












                                                                        
                                                                  







                                                               

                                                                       


                                            
                                             
                                                                     

                                                          







                                                                     







                                                                  


                                                            



                                                               




















                                                                             

                                                                       
                                             


                                                                        








                                                                              
                                                                         

                                                   

                                                           
                                                                     

                                                                    
                                                               

                                                                



















                                                                             












                                                                              
 




                                                              














                                                                           
                                                    
                                                                              

                                                                 
 
                                                                       
                                                              
                                                      

                                                     

                                                           


                                                                        



                                                                           
 
                                                            
                                                          






                                                                           
                                                                        

                                                          
                                                                   
                                                         
                                         




                                                    



                                                                




                                               
                                                                              
 
                                                      





                                                     





                                                                         




                            
                                          













                                                                 
                                                                  


                             


                                                               







                                                         
                                           








                                                                
 

                                                        
                         

                                               












                                                                               
                                                                     




                                                                  

                                                   
































                                                                           


                 
                                                                      

                                                 
                                                              
                                                                    

                                                          



                                           

              







                                                                         

                                                                          
 



                                                          
                                                                


                                                                       


                                                                            

                                                            

                                      


                                                                               



                                                                           












                                                                         
                                           

                                                                  

                                                              


                                                                          
                                                                






                                                                                
                                                        

                                                                     



                                                     

















                                                                     
                                                    
                                                     

                                                        
                                                  
                                                   
 
                                                                       

                                                              


                                                                  

                                                                      
                                                                     

                                                                    
                                                                           



                                                                        
                                                                        

                                                                
                                                               
                                                     
                                         



                                                               



                                                                    




                                                   
                                               


                                                 
                                                              





                                                             


                                                                          




                                                                         
                                                                           









                                                                        










                                                                             
                                                                      
                                                               
                                                             







                                                            
                                              








                                                           
                                                      

                                                               
                                                   















                                                                     
                                                                        





                                                              
                                                        






                                                                       
                                                                      










                                                                          
                                              









                                                           
                                                      

                                                               
                                                   
















                                                                     
                                                                        

                                                               
                                                        





                                                               
                                                                      













                                                                          
                                              





                                    
                                                      
 
                                                                        
                                                                   
                                                        






                                                                            
                                                                      







                                                                            





















                                                                            
                                                       





                                             
                                                   


                                                                   

                                                                           





                                                         
                                                                            


                                                 
                      



                                                 

                                                
                                                              




                                                                               
                                                           

         

                                                                     


                                                             
                                                                         
 
                                                         


                                                             
                                                                      
                                                                            
                                 



                                         
                                                                              

                                                                           
                                 

                 
                                                           
                         






                                                                           

                                                                             

                                                                          
                                 







                                                                           
                                 

                 
                                                                   




                                                                              
                                 

                 
                                                                





                                                                        

                                                                            


                                                                    
                                                                          








                                                                              
                                 







                                                                             

                                                                              

                                  
                                                 
                                                             
 
                                            


                                                                 


                                        

 
                                                  












                                                                 
                                                                     








                                                                   
                                                   












                                                                 
                                                                     








                                                                     
                                                        

                                               
                                              








                                                                 

                                                                        
                                                                   

                                                        




                                                                      


                                                                            




                                                   
                                                  






                                                                   
                                                  



                                                      

                                                                  



                                               

                                                           




                                     
                                                 





                                                       











































































                                                                               
                                                                               






                                                                           
                                          













                                                          
                                                      













































                                                                               
                        







                                                                      

                                                                    
                                                               
                                                    













                                                                            
                                                                      


                                                                              
                                                                       






































                                                                              
                                                                                






























































                                                                            
                                            






                                                                      
                                            

















                                                                              
                                            








                                                                
                                            







                                                                 
                                              





                                    

                                                                        
                                                                   
                                                        




                                                             
                                                                     


                                                               
                                                             









                                                                        
                                              


























                                                                    

                                                                        
                                                                   
                                                        












                                                                          
                                                                     

                                                                              
                                                                       

























































                                                                                
                                          


                                
                                                  



















                                                                      
                                                                          







































































                                                                           
                                                        



















                                                                              
                                                         










                                                        
                                                  


                     
                                     
                                                 
                                                                              
                                             


                                                                     











                                                          


                                                                            




                                                         
                                                    





                                                 
                                                                        
                                             
                                                                      



                                                           

                                                         

                               









                                                                            









































                                                                           
                                                 
                            
                                                                         










                                                                             
                                                

                                                        
                                                                          



                                                                               
                                                                             






                                                                            
 























                                                                     
                                                   
 
                                                                  

                   
                                            
                                                    
                                              






                                                                     





                                                              
                                                 



                                                             
                          










                                                                             
                           
                                   

                                                        
                                                          
                                                       
                                                




                                                             



                                     




                                                                    
                 

                                             





                             

                                                                

                                               
                                                                  


















                                                                          










                                                                               

                                                           

                                               

                                                                  









                                                                


                                             
                                                      
                                                      
                                                 















                                                   

                                                                




                                               

                                                                          

                                       
                                                 





                                                        
                                              

                                                 
                                                 
                                
                
 
                                            





                                                                            

                                              




                                                                         


                                                                          






                                                                         
                                               








                                                                           
















                                                                             

                                                              


                                                                    





                                                                       
                   


                                                     
                         

                                                         
                                                                   

                                                               




                                                                       


                                                                  




                                                                             
                                              
                                                                   


                                                                




                                                                              






                                                                                
                                             
                                                             
                                                      
                                                               
            
                                                             



                 


                                                              
 
                                             





                                                 
 
                                                  
                                                  
 
                                                     



                                                             

                                                     

                                                              

                                                 
  
/*
 * Cypress APA trackpad with I2C interface
 *
 * Author: Dudley Du <dudl@cypress.com>
 *
 * Copyright (C) 2014-2015 Cypress Semiconductor, Inc.
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive for
 * more details.
 */

#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <linux/crc-itu-t.h>
#include <linux/pm_runtime.h>
#include "cyapa.h"


/* Macro of TSG firmware image */
#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE      0x80
#define CYAPA_TSG_IMG_FW_HDR_SIZE           13
#define CYAPA_TSG_FW_ROW_SIZE               (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE)
#define CYAPA_TSG_IMG_START_ROW_NUM         0x002e
#define CYAPA_TSG_IMG_END_ROW_NUM           0x01fe
#define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff
#define CYAPA_TSG_IMG_MAX_RECORDS           (CYAPA_TSG_IMG_END_ROW_NUM - \
				CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1)
#define CYAPA_TSG_IMG_READ_SIZE             (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2)
#define CYAPA_TSG_START_OF_APPLICATION      0x1700
#define CYAPA_TSG_APP_INTEGRITY_SIZE        60
#define CYAPA_TSG_FLASH_MAP_METADATA_SIZE   60
#define CYAPA_TSG_BL_KEY_SIZE               8

#define CYAPA_TSG_MAX_CMD_SIZE              256

/* Macro of PIP interface */
#define PIP_BL_INITIATE_RESP_LEN            11
#define PIP_BL_FAIL_EXIT_RESP_LEN           11
#define PIP_BL_FAIL_EXIT_STATUS_CODE        0x0c
#define PIP_BL_VERIFY_INTEGRITY_RESP_LEN    12
#define PIP_BL_INTEGRITY_CHEKC_PASS         0x00
#define PIP_BL_BLOCK_WRITE_RESP_LEN         11

#define PIP_TOUCH_REPORT_ID         0x01
#define PIP_BTN_REPORT_ID           0x03
#define PIP_WAKEUP_EVENT_REPORT_ID  0x04
#define PIP_PUSH_BTN_REPORT_ID      0x06
#define GEN5_OLD_PUSH_BTN_REPORT_ID 0x05  /* Special for old Gen5 TP. */
#define PIP_PROXIMITY_REPORT_ID     0x07

#define PIP_PROXIMITY_REPORT_SIZE	6
#define PIP_PROXIMITY_DISTANCE_OFFSET	0x05
#define PIP_PROXIMITY_DISTANCE_MASK	0x01

#define PIP_TOUCH_REPORT_HEAD_SIZE     7
#define PIP_TOUCH_REPORT_MAX_SIZE      127
#define PIP_BTN_REPORT_HEAD_SIZE       6
#define PIP_BTN_REPORT_MAX_SIZE        14
#define PIP_WAKEUP_EVENT_SIZE          4

#define PIP_NUMBER_OF_TOUCH_OFFSET  5
#define PIP_NUMBER_OF_TOUCH_MASK    0x1f
#define PIP_BUTTONS_OFFSET          5
#define PIP_BUTTONS_MASK            0x0f
#define PIP_GET_EVENT_ID(reg)       (((reg) >> 5) & 0x03)
#define PIP_GET_TOUCH_ID(reg)       ((reg) & 0x1f)
#define PIP_TOUCH_TYPE_FINGER	    0x00
#define PIP_TOUCH_TYPE_PROXIMITY    0x01
#define PIP_TOUCH_TYPE_HOVER	    0x02
#define PIP_GET_TOUCH_TYPE(reg)     ((reg) & 0x07)

#define RECORD_EVENT_NONE        0
#define RECORD_EVENT_TOUCHDOWN	 1
#define RECORD_EVENT_DISPLACE    2
#define RECORD_EVENT_LIFTOFF     3

#define PIP_SENSING_MODE_MUTUAL_CAP_FINE   0x00
#define PIP_SENSING_MODE_SELF_CAP          0x02

#define PIP_SET_PROXIMITY	0x49

/* Macro of Gen5 */
#define GEN5_BL_MAX_OUTPUT_LENGTH     0x0100
#define GEN5_APP_MAX_OUTPUT_LENGTH    0x00fe

#define GEN5_POWER_STATE_ACTIVE              0x01
#define GEN5_POWER_STATE_LOOK_FOR_TOUCH      0x02
#define GEN5_POWER_STATE_READY               0x03
#define GEN5_POWER_STATE_IDLE                0x04
#define GEN5_POWER_STATE_BTN_ONLY            0x05
#define GEN5_POWER_STATE_OFF                 0x06

#define GEN5_POWER_READY_MAX_INTRVL_TIME  50   /* Unit: ms */
#define GEN5_POWER_IDLE_MAX_INTRVL_TIME   250  /* Unit: ms */

#define GEN5_CMD_GET_PARAMETER		     0x05
#define GEN5_CMD_SET_PARAMETER		     0x06
#define GEN5_PARAMETER_ACT_INTERVL_ID        0x4d
#define GEN5_PARAMETER_ACT_INTERVL_SIZE      1
#define GEN5_PARAMETER_ACT_LFT_INTERVL_ID    0x4f
#define GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE  2
#define GEN5_PARAMETER_LP_INTRVL_ID          0x4c
#define GEN5_PARAMETER_LP_INTRVL_SIZE        2

#define GEN5_PARAMETER_DISABLE_PIP_REPORT    0x08

#define GEN5_BL_REPORT_DESCRIPTOR_SIZE            0x1d
#define GEN5_BL_REPORT_DESCRIPTOR_ID              0xfe
#define GEN5_APP_REPORT_DESCRIPTOR_SIZE           0xee
#define GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE  0xfa
#define GEN5_APP_REPORT_DESCRIPTOR_ID             0xf6

#define GEN5_RETRIEVE_MUTUAL_PWC_DATA        0x00
#define GEN5_RETRIEVE_SELF_CAP_PWC_DATA      0x01

#define GEN5_RETRIEVE_DATA_ELEMENT_SIZE_MASK 0x07

#define GEN5_CMD_EXECUTE_PANEL_SCAN          0x2a
#define GEN5_CMD_RETRIEVE_PANEL_SCAN         0x2b
#define GEN5_PANEL_SCAN_MUTUAL_RAW_DATA      0x00
#define GEN5_PANEL_SCAN_MUTUAL_BASELINE      0x01
#define GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT     0x02
#define GEN5_PANEL_SCAN_SELF_RAW_DATA        0x03
#define GEN5_PANEL_SCAN_SELF_BASELINE        0x04
#define GEN5_PANEL_SCAN_SELF_DIFFCOUNT       0x05

/* The offset only valid for retrieve PWC and panel scan commands */
#define GEN5_RESP_DATA_STRUCTURE_OFFSET      10
#define GEN5_PWC_DATA_ELEMENT_SIZE_MASK      0x07


struct cyapa_pip_touch_record {
	/*
	 * Bit 7 - 3: reserved
	 * Bit 2 - 0: touch type;
	 *            0 : standard finger;
	 *            1 : proximity (Start supported in Gen5 TP).
	 *            2 : finger hover (defined, but not used yet.)
	 *            3 - 15 : reserved.
	 */
	u8 touch_type;

	/*
	 * Bit 7: indicates touch liftoff status.
	 *		0 : touch is currently on the panel.
	 *		1 : touch record indicates a liftoff.
	 * Bit 6 - 5: indicates an event associated with this touch instance
	 *		0 : no event
	 *		1 : touchdown
	 *		2 : significant displacement (> active distance)
	 *		3 : liftoff (record reports last known coordinates)
	 * Bit 4 - 0: An arbitrary ID tag associated with a finger
	 *		to allow tracking a touch as it moves around the panel.
	 */
	u8 touch_tip_event_id;

	/* Bit 7 - 0 of X-axis coordinate of the touch in pixel. */
	u8 x_lo;

	/* Bit 15 - 8 of X-axis coordinate of the touch in pixel. */
	u8 x_hi;

	/* Bit 7 - 0 of Y-axis coordinate of the touch in pixel. */
	u8 y_lo;

	/* Bit 15 - 8 of Y-axis coordinate of the touch in pixel. */
	u8 y_hi;

	/*
	 * The meaning of this value is different when touch_type is different.
	 * For standard finger type:
	 *	Touch intensity in counts, pressure value.
	 * For proximity type (Start supported in Gen5 TP):
	 *	The distance, in surface units, between the contact and
	 *	the surface.
	 **/
	u8 z;

	/*
	 * The length of the major axis of the ellipse of contact between
	 * the finger and the panel (ABS_MT_TOUCH_MAJOR).
	 */
	u8 major_axis_len;

	/*
	 * The length of the minor axis of the ellipse of contact between
	 * the finger and the panel (ABS_MT_TOUCH_MINOR).
	 */
	u8 minor_axis_len;

	/*
	 * The length of the major axis of the approaching tool.
	 * (ABS_MT_WIDTH_MAJOR)
	 */
	u8 major_tool_len;

	/*
	 * The length of the minor axis of the approaching tool.
	 * (ABS_MT_WIDTH_MINOR)
	 */
	u8 minor_tool_len;

	/*
	 * The angle between the panel vertical axis and
	 * the major axis of the contact ellipse. This value is an 8-bit
	 * signed integer. The range is -127 to +127 (corresponding to
	 * -90 degree and +90 degree respectively).
	 * The positive direction is clockwise from the vertical axis.
	 * If the ellipse of contact degenerates into a circle,
	 * orientation is reported as 0.
	 */
	u8 orientation;
} __packed;

struct cyapa_pip_report_data {
	u8 report_head[PIP_TOUCH_REPORT_HEAD_SIZE];
	struct cyapa_pip_touch_record touch_records[10];
} __packed;

struct cyapa_tsg_bin_image_head {
	u8 head_size;  /* Unit: bytes, including itself. */
	u8 ttda_driver_major_version;  /* Reserved as 0. */
	u8 ttda_driver_minor_version;  /* Reserved as 0. */
	u8 fw_major_version;
	u8 fw_minor_version;
	u8 fw_revision_control_number[8];
	u8 silicon_id_hi;
	u8 silicon_id_lo;
	u8 chip_revision;
	u8 family_id;
	u8 bl_ver_maj;
	u8 bl_ver_min;
} __packed;

struct cyapa_tsg_bin_image_data_record {
	u8 flash_array_id;
	__be16 row_number;
	/* The number of bytes of flash data contained in this record. */
	__be16 record_len;
	/* The flash program data. */
	u8 record_data[CYAPA_TSG_FW_ROW_SIZE];
} __packed;

struct cyapa_tsg_bin_image {
	struct cyapa_tsg_bin_image_head image_head;
	struct cyapa_tsg_bin_image_data_record records[0];
} __packed;

struct pip_bl_packet_start {
	u8 sop;  /* Start of packet, must be 01h */
	u8 cmd_code;
	__le16 data_length;  /* Size of data parameter start from data[0] */
} __packed;

struct pip_bl_packet_end {
	__le16 crc;
	u8 eop;  /* End of packet, must be 17h */
} __packed;

struct pip_bl_cmd_head {
	__le16 addr;   /* Output report register address, must be 0004h */
	/* Size of packet not including output report register address */
	__le16 length;
	u8 report_id;  /* Bootloader output report id, must be 40h */
	u8 rsvd;  /* Reserved, must be 0 */
	struct pip_bl_packet_start packet_start;
	u8 data[0];  /* Command data variable based on commands */
} __packed;

/* Initiate bootload command data structure. */
struct pip_bl_initiate_cmd_data {
	/* Key must be "A5h 01h 02h 03h FFh FEh FDh 5Ah" */
	u8 key[CYAPA_TSG_BL_KEY_SIZE];
	u8 metadata_raw_parameter[CYAPA_TSG_FLASH_MAP_METADATA_SIZE];
	__le16 metadata_crc;
} __packed;

struct tsg_bl_metadata_row_params {
	__le16 size;
	__le16 maximum_size;
	__le32 app_start;
	__le16 app_len;
	__le16 app_crc;
	__le32 app_entry;
	__le32 upgrade_start;
	__le16 upgrade_len;
	__le16 entry_row_crc;
	u8 padding[36];  /* Padding data must be 0 */
	__le16 metadata_crc;  /* CRC starts at offset of 60 */
} __packed;

/* Bootload program and verify row command data structure */
struct tsg_bl_flash_row_head {
	u8 flash_array_id;
	__le16 flash_row_id;
	u8 flash_data[0];
} __packed;

struct pip_app_cmd_head {
	__le16 addr;   /* Output report register address, must be 0004h */
	/* Size of packet not including output report register address */
	__le16 length;
	u8 report_id;  /* Application output report id, must be 2Fh */
	u8 rsvd;  /* Reserved, must be 0 */
	/*
	 * Bit 7: reserved, must be 0.
	 * Bit 6-0: command code.
	 */
	u8 cmd_code;
	u8 parameter_data[0];  /* Parameter data variable based on cmd_code */
} __packed;

/* Application get/set parameter command data structure */
struct gen5_app_set_parameter_data {
	u8 parameter_id;
	u8 parameter_size;
	__le32 value;
} __packed;

struct gen5_app_get_parameter_data {
	u8 parameter_id;
} __packed;

struct gen5_retrieve_panel_scan_data {
	__le16 read_offset;
	__le16 read_elements;
	u8 data_id;
} __packed;

u8 pip_read_sys_info[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x02 };
u8 pip_bl_read_app_info[] = { 0x04, 0x00, 0x0b, 0x00, 0x40, 0x00,
		0x01, 0x3c, 0x00, 0x00, 0xb0, 0x42, 0x17
	};

static u8 cyapa_pip_bl_cmd_key[] = { 0xa5, 0x01, 0x02, 0x03,
	0xff, 0xfe, 0xfd, 0x5a };

static int cyapa_pip_event_process(struct cyapa *cyapa,
				   struct cyapa_pip_report_data *report_data);

int cyapa_pip_cmd_state_initialize(struct cyapa *cyapa)
{
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;

	init_completion(&pip->cmd_ready);
	atomic_set(&pip->cmd_issued, 0);
	mutex_init(&pip->cmd_lock);

	mutex_init(&pip->pm_stage_lock);
	pip->pm_stage = CYAPA_PM_DEACTIVE;

	pip->resp_sort_func = NULL;
	pip->in_progress_cmd = PIP_INVALID_CMD;
	pip->resp_data = NULL;
	pip->resp_len = NULL;

	cyapa->dev_pwr_mode = UNINIT_PWR_MODE;
	cyapa->dev_sleep_time = UNINIT_SLEEP_TIME;

	return 0;
}

/* Return negative errno, or else the number of bytes read. */
ssize_t cyapa_i2c_pip_read(struct cyapa *cyapa, u8 *buf, size_t size)
{
	int ret;

	if (size == 0)
		return 0;

	if (!buf || size > CYAPA_REG_MAP_SIZE)
		return -EINVAL;

	ret = i2c_master_recv(cyapa->client, buf, size);

	if (ret != size)
		return (ret < 0) ? ret : -EIO;
	return size;
}

/**
 * Return a negative errno code else zero on success.
 */
ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size)
{
	int ret;

	if (!buf || !size)
		return -EINVAL;

	ret = i2c_master_send(cyapa->client, buf, size);

	if (ret != size)
		return (ret < 0) ? ret : -EIO;

	return 0;
}

static void cyapa_set_pip_pm_state(struct cyapa *cyapa,
				   enum cyapa_pm_stage pm_stage)
{
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;

	mutex_lock(&pip->pm_stage_lock);
	pip->pm_stage = pm_stage;
	mutex_unlock(&pip->pm_stage_lock);
}

static void cyapa_reset_pip_pm_state(struct cyapa *cyapa)
{
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;

	/* Indicates the pip->pm_stage is not valid. */
	mutex_lock(&pip->pm_stage_lock);
	pip->pm_stage = CYAPA_PM_DEACTIVE;
	mutex_unlock(&pip->pm_stage_lock);
}

static enum cyapa_pm_stage cyapa_get_pip_pm_state(struct cyapa *cyapa)
{
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
	enum cyapa_pm_stage pm_stage;

	mutex_lock(&pip->pm_stage_lock);
	pm_stage = pip->pm_stage;
	mutex_unlock(&pip->pm_stage_lock);

	return pm_stage;
}

/**
 * This function is aimed to dump all not read data in Gen5 trackpad
 * before send any command, otherwise, the interrupt line will be blocked.
 */
int cyapa_empty_pip_output_data(struct cyapa *cyapa,
		u8 *buf, int *len, cb_sort func)
{
	struct input_dev *input = cyapa->input;
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
	enum cyapa_pm_stage pm_stage = cyapa_get_pip_pm_state(cyapa);
	int length;
	int report_count;
	int empty_count;
	int buf_len;
	int error;

	buf_len = 0;
	if (len) {
		buf_len = (*len < CYAPA_REG_MAP_SIZE) ?
				*len : CYAPA_REG_MAP_SIZE;
		*len = 0;
	}

	report_count = 8;  /* max 7 pending data before command response data */
	empty_count = 0;
	do {
		/*
		 * Depending on testing in cyapa driver, there are max 5 "02 00"
		 * packets between two valid buffered data report in firmware.
		 * So in order to dump all buffered data out and
		 * make interrupt line release for reassert again,
		 * we must set the empty_count check value bigger than 5 to
		 * make it work. Otherwise, in some situation,
		 * the interrupt line may unable to reactive again,
		 * which will cause trackpad device unable to
		 * report data any more.
		 * for example, it may happen in EFT and ESD testing.
		 */
		if (empty_count > 5)
			return 0;

		error = cyapa_i2c_pip_read(cyapa, pip->empty_buf,
				PIP_RESP_LENGTH_SIZE);
		if (error < 0)
			return error;

		length = get_unaligned_le16(pip->empty_buf);
		if (length == PIP_RESP_LENGTH_SIZE) {
			empty_count++;
			continue;
		} else if (length > CYAPA_REG_MAP_SIZE) {
			/* Should not happen */
			return -EINVAL;
		} else if (length == 0) {
			/* Application or bootloader launch data polled out. */
			length = PIP_RESP_LENGTH_SIZE;
			if (buf && buf_len && func &&
				func(cyapa, pip->empty_buf, length)) {
				length = min(buf_len, length);
				memcpy(buf, pip->empty_buf, length);
				*len = length;
				/* Response found, success. */
				return 0;
			}
			continue;
		}

		error = cyapa_i2c_pip_read(cyapa, pip->empty_buf, length);
		if (error < 0)
			return error;

		report_count--;
		empty_count = 0;
		length = get_unaligned_le16(pip->empty_buf);
		if (length <= PIP_RESP_LENGTH_SIZE) {
			empty_count++;
		} else if (buf && buf_len && func &&
			func(cyapa, pip->empty_buf, length)) {
			length = min(buf_len, length);
			memcpy(buf, pip->empty_buf, length);
			*len = length;
			/* Response found, success. */
			return 0;
		} else if (cyapa->operational && input && input->users &&
			   (pm_stage == CYAPA_PM_RUNTIME_RESUME ||
			    pm_stage == CYAPA_PM_RUNTIME_SUSPEND)) {
			/* Parse the data and report it if it's valid. */
			cyapa_pip_event_process(cyapa,
			       (struct cyapa_pip_report_data *)pip->empty_buf);
		}

		error = -EINVAL;
	} while (report_count);

	return error;
}

static int cyapa_do_i2c_pip_cmd_irq_sync(
		struct cyapa *cyapa,
		u8 *cmd, size_t cmd_len,
		unsigned long timeout)
{
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
	int error;

	/* Wait for interrupt to set ready completion */
	init_completion(&pip->cmd_ready);

	atomic_inc(&pip->cmd_issued);
	error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len);
	if (error) {
		atomic_dec(&pip->cmd_issued);
		return (error < 0) ? error : -EIO;
	}

	/* Wait for interrupt to indicate command is completed. */
	timeout = wait_for_completion_timeout(&pip->cmd_ready,
				msecs_to_jiffies(timeout));
	if (timeout == 0) {
		atomic_dec(&pip->cmd_issued);
		return -ETIMEDOUT;
	}

	return 0;
}

static int cyapa_do_i2c_pip_cmd_polling(
		struct cyapa *cyapa,
		u8 *cmd, size_t cmd_len,
		u8 *resp_data, int *resp_len,
		unsigned long timeout,
		cb_sort func)
{
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
	int tries;
	int length;
	int error;

	atomic_inc(&pip->cmd_issued);
	error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len);
	if (error) {
		atomic_dec(&pip->cmd_issued);
		return error < 0 ? error : -EIO;
	}

	length = resp_len ? *resp_len : 0;
	if (resp_data && resp_len && length != 0 && func) {
		tries = timeout / 5;
		do {
			usleep_range(3000, 5000);
			*resp_len = length;
			error = cyapa_empty_pip_output_data(cyapa,
					resp_data, resp_len, func);
			if (error || *resp_len == 0)
				continue;
			else
				break;
		} while (--tries > 0);
		if ((error || *resp_len == 0) || tries <= 0)
			error = error ? error : -ETIMEDOUT;
	}

	atomic_dec(&pip->cmd_issued);
	return error;
}

int cyapa_i2c_pip_cmd_irq_sync(
		struct cyapa *cyapa,
		u8 *cmd, int cmd_len,
		u8 *resp_data, int *resp_len,
		unsigned long timeout,
		cb_sort func,
		bool irq_mode)
{
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
	int error;

	if (!cmd || !cmd_len)
		return -EINVAL;

	/* Commands must be serialized. */
	error = mutex_lock_interruptible(&pip->cmd_lock);
	if (error)
		return error;

	pip->resp_sort_func = func;
	pip->resp_data = resp_data;
	pip->resp_len = resp_len;

	if (cmd_len >= PIP_MIN_APP_CMD_LENGTH &&
			cmd[4] == PIP_APP_CMD_REPORT_ID) {
		/* Application command */
		pip->in_progress_cmd = cmd[6] & 0x7f;
	} else if (cmd_len >= PIP_MIN_BL_CMD_LENGTH &&
			cmd[4] == PIP_BL_CMD_REPORT_ID) {
		/* Bootloader command */
		pip->in_progress_cmd = cmd[7];
	}

	/* Send command data, wait and read output response data's length. */
	if (irq_mode) {
		pip->is_irq_mode = true;
		error = cyapa_do_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len,
							timeout);
		if (error == -ETIMEDOUT && resp_data &&
				resp_len && *resp_len != 0 && func) {
			/*
			 * For some old version, there was no interrupt for
			 * the command response data, so need to poll here
			 * to try to get the response data.
			 */
			error = cyapa_empty_pip_output_data(cyapa,
					resp_data, resp_len, func);
			if (error || *resp_len == 0)
				error = error ? error : -ETIMEDOUT;
		}
	} else {
		pip->is_irq_mode = false;
		error = cyapa_do_i2c_pip_cmd_polling(cyapa, cmd, cmd_len,
				resp_data, resp_len, timeout, func);
	}

	pip->resp_sort_func = NULL;
	pip->resp_data = NULL;
	pip->resp_len = NULL;
	pip->in_progress_cmd = PIP_INVALID_CMD;

	mutex_unlock(&pip->cmd_lock);
	return error;
}

bool cyapa_sort_tsg_pip_bl_resp_data(struct cyapa *cyapa,
		u8 *data, int len)
{
	if (!data || len < PIP_MIN_BL_RESP_LENGTH)
		return false;

	/* Bootloader input report id 30h */
	if (data[PIP_RESP_REPORT_ID_OFFSET] == PIP_BL_RESP_REPORT_ID &&
			data[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY &&
			data[PIP_RESP_BL_SOP_OFFSET] == PIP_SOP_KEY)
		return true;

	return false;
}

bool cyapa_sort_tsg_pip_app_resp_data(struct cyapa *cyapa,
		u8 *data, int len)
{
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
	int resp_len;

	if (!data || len < PIP_MIN_APP_RESP_LENGTH)
		return false;

	if (data[PIP_RESP_REPORT_ID_OFFSET] == PIP_APP_RESP_REPORT_ID &&
			data[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY) {
		resp_len = get_unaligned_le16(&data[PIP_RESP_LENGTH_OFFSET]);
		if (GET_PIP_CMD_CODE(data[PIP_RESP_APP_CMD_OFFSET]) == 0x00 &&
			resp_len == PIP_UNSUPPORTED_CMD_RESP_LENGTH &&
			data[5] == pip->in_progress_cmd) {
			/* Unsupported command code */
			return false;
		} else if (GET_PIP_CMD_CODE(data[PIP_RESP_APP_CMD_OFFSET]) ==
				pip->in_progress_cmd) {
			/* Correct command response received */
			return true;
		}
	}

	return false;
}

static bool cyapa_sort_pip_application_launch_data(struct cyapa *cyapa,
		u8 *buf, int len)
{
	if (buf == NULL || len < PIP_RESP_LENGTH_SIZE)
		return false;

	/*
	 * After reset or power on, trackpad device always sets to 0x00 0x00
	 * to indicate a reset or power on event.
	 */
	if (buf[0] == 0 && buf[1] == 0)
		return true;

	return false;
}

static bool cyapa_sort_gen5_hid_descriptor_data(struct cyapa *cyapa,
		u8 *buf, int len)
{
	int resp_len;
	int max_output_len;

	/* Check hid descriptor. */
	if (len != PIP_HID_DESCRIPTOR_SIZE)
		return false;

	resp_len = get_unaligned_le16(&buf[PIP_RESP_LENGTH_OFFSET]);
	max_output_len = get_unaligned_le16(&buf[16]);
	if (resp_len == PIP_HID_DESCRIPTOR_SIZE) {
		if (buf[PIP_RESP_REPORT_ID_OFFSET] == PIP_HID_BL_REPORT_ID &&
				max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) {
			/* BL mode HID Descriptor */
			return true;
		} else if ((buf[PIP_RESP_REPORT_ID_OFFSET] ==
				PIP_HID_APP_REPORT_ID) &&
				max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) {
			/* APP mode HID Descriptor */
			return true;
		}
	}

	return false;
}

static bool cyapa_sort_pip_deep_sleep_data(struct cyapa *cyapa,
		u8 *buf, int len)
{
	if (len == PIP_DEEP_SLEEP_RESP_LENGTH &&
		buf[PIP_RESP_REPORT_ID_OFFSET] ==
			PIP_APP_DEEP_SLEEP_REPORT_ID &&
		(buf[4] & PIP_DEEP_SLEEP_OPCODE_MASK) ==
			PIP_DEEP_SLEEP_OPCODE)
		return true;
	return false;
}

static int gen5_idle_state_parse(struct cyapa *cyapa)
{
	u8 resp_data[PIP_HID_DESCRIPTOR_SIZE];
	int max_output_len;
	int length;
	u8 cmd[2];
	int ret;
	int error;

	/*
	 * Dump all buffered data firstly for the situation
	 * when the trackpad is just power on the cyapa go here.
	 */
	cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);

	memset(resp_data, 0, sizeof(resp_data));
	ret = cyapa_i2c_pip_read(cyapa, resp_data, 3);
	if (ret != 3)
		return ret < 0 ? ret : -EIO;

	length = get_unaligned_le16(&resp_data[PIP_RESP_LENGTH_OFFSET]);
	if (length == PIP_RESP_LENGTH_SIZE) {
		/* Normal state of Gen5 with no data to response */
		cyapa->gen = CYAPA_GEN5;

		cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);

		/* Read description from trackpad device */
		cmd[0] = 0x01;
		cmd[1] = 0x00;
		length = PIP_HID_DESCRIPTOR_SIZE;
		error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
				cmd, PIP_RESP_LENGTH_SIZE,
				resp_data, &length,
				300,
				cyapa_sort_gen5_hid_descriptor_data,
				false);
		if (error)
			return error;

		length = get_unaligned_le16(
				&resp_data[PIP_RESP_LENGTH_OFFSET]);
		max_output_len = get_unaligned_le16(&resp_data[16]);
		if ((length == PIP_HID_DESCRIPTOR_SIZE ||
				length == PIP_RESP_LENGTH_SIZE) &&
			(resp_data[PIP_RESP_REPORT_ID_OFFSET] ==
				PIP_HID_BL_REPORT_ID) &&
			max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) {
			/* BL mode HID Description read */
			cyapa->state = CYAPA_STATE_GEN5_BL;
		} else if ((length == PIP_HID_DESCRIPTOR_SIZE ||
				length == PIP_RESP_LENGTH_SIZE) &&
			(resp_data[PIP_RESP_REPORT_ID_OFFSET] ==
				PIP_HID_APP_REPORT_ID) &&
			max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) {
			/* APP mode HID Description read */
			cyapa->state = CYAPA_STATE_GEN5_APP;
		} else {
			/* Should not happen!!! */
			cyapa->state = CYAPA_STATE_NO_DEVICE;
		}
	}

	return 0;
}

static int gen5_hid_description_header_parse(struct cyapa *cyapa, u8 *reg_data)
{
	int length;
	u8 resp_data[32];
	int max_output_len;
	int ret;

	/* 0x20 0x00 0xF7 is Gen5 Application HID Description Header;
	 * 0x20 0x00 0xFF is Gen5 Bootloader HID Description Header.
	 *
	 * Must read HID Description content through out,
	 * otherwise Gen5 trackpad cannot response next command
	 * or report any touch or button data.
	 */
	ret = cyapa_i2c_pip_read(cyapa, resp_data,
			PIP_HID_DESCRIPTOR_SIZE);
	if (ret != PIP_HID_DESCRIPTOR_SIZE)
		return ret < 0 ? ret : -EIO;
	length = get_unaligned_le16(&resp_data[PIP_RESP_LENGTH_OFFSET]);
	max_output_len = get_unaligned_le16(&resp_data[16]);
	if (length == PIP_RESP_LENGTH_SIZE) {
		if (reg_data[PIP_RESP_REPORT_ID_OFFSET] ==
				PIP_HID_BL_REPORT_ID) {
			/*
			 * BL mode HID Description has been previously
			 * read out.
			 */
			cyapa->gen = CYAPA_GEN5;
			cyapa->state = CYAPA_STATE_GEN5_BL;
		} else {
			/*
			 * APP mode HID Description has been previously
			 * read out.
			 */
			cyapa->gen = CYAPA_GEN5;
			cyapa->state = CYAPA_STATE_GEN5_APP;
		}
	} else if (length == PIP_HID_DESCRIPTOR_SIZE &&
			resp_data[2] == PIP_HID_BL_REPORT_ID &&
			max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) {
		/* BL mode HID Description read. */
		cyapa->gen = CYAPA_GEN5;
		cyapa->state = CYAPA_STATE_GEN5_BL;
	} else if (length == PIP_HID_DESCRIPTOR_SIZE &&
			(resp_data[PIP_RESP_REPORT_ID_OFFSET] ==
				PIP_HID_APP_REPORT_ID) &&
			max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) {
		/* APP mode HID Description read. */
		cyapa->gen = CYAPA_GEN5;
		cyapa->state = CYAPA_STATE_GEN5_APP;
	} else {
		/* Should not happen!!! */
		cyapa->state = CYAPA_STATE_NO_DEVICE;
	}

	return 0;
}

static int gen5_report_data_header_parse(struct cyapa *cyapa, u8 *reg_data)
{
	int length;

	length = get_unaligned_le16(&reg_data[PIP_RESP_LENGTH_OFFSET]);
	switch (reg_data[PIP_RESP_REPORT_ID_OFFSET]) {
	case PIP_TOUCH_REPORT_ID:
		if (length < PIP_TOUCH_REPORT_HEAD_SIZE ||
			length > PIP_TOUCH_REPORT_MAX_SIZE)
			return -EINVAL;
		break;
	case PIP_BTN_REPORT_ID:
	case GEN5_OLD_PUSH_BTN_REPORT_ID:
	case PIP_PUSH_BTN_REPORT_ID:
		if (length < PIP_BTN_REPORT_HEAD_SIZE ||
			length > PIP_BTN_REPORT_MAX_SIZE)
			return -EINVAL;
		break;
	case PIP_WAKEUP_EVENT_REPORT_ID:
		if (length != PIP_WAKEUP_EVENT_SIZE)
			return -EINVAL;
		break;
	default:
		return -EINVAL;
	}

	cyapa->gen = CYAPA_GEN5;
	cyapa->state = CYAPA_STATE_GEN5_APP;
	return 0;
}

static int gen5_cmd_resp_header_parse(struct cyapa *cyapa, u8 *reg_data)
{
	struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
	int length;
	int ret;

	/*
	 * Must read report data through out,
	 * otherwise Gen5 trackpad cannot response next command
	 * or report any touch or button data.
	 */
	length = get_unaligned_le16(&reg_data[PIP_RESP_LENGTH_OFFSET]);
	ret = cyapa_i2c_pip_read(cyapa, pip->empty_buf, length);
	if (ret != length)
		return ret < 0 ? ret : -EIO;

	if (length == PIP_RESP_LENGTH_SIZE) {
		/* Previous command has read the data through out. */
		if (reg_data[PIP_RESP_REPORT_ID_OFFSET] ==
				PIP_BL_RESP_REPORT_ID) {
			/* Gen5 BL command response data detected */
			cyapa->gen = CYAPA_GEN5;
			cyapa->state = CYAPA_STATE_GEN5_BL;
		} else {
			/* Gen5 APP command response data detected */
			cyapa->gen = CYAPA_GEN5;
			cyapa->state = CYAPA_STATE_GEN5_APP;
		}
	} else if ((pip->empty_buf[PIP_RESP_REPORT_ID_OFFSET] ==
				PIP_BL_RESP_REPORT_ID) &&
			(pip->empty_buf[PIP_RESP_RSVD_OFFSET] ==
				PIP_RESP_RSVD_KEY) &&
			(pip->empty_buf[PIP_RESP_BL_SOP_OFFSET] ==
				PIP_SOP_KEY) &&
			(pip->empty_buf[length - 1] ==
				PIP_EOP_KEY)) {
		/* Gen5 BL command response data detected */
		cyapa->gen = CYAPA_GEN5;
		cyapa->state = CYAPA_STATE_GEN5_BL;
	} else if (pip->empty_buf[PIP_RESP_REPORT_ID_OFFSET] ==
				PIP_APP_RESP_REPORT_ID &&
			pip->empty_buf[PIP_RESP_RSVD_OFFSET] ==
				PIP_RESP_RSVD_KEY) {
		/* Gen5 APP command response data detected */
		cyapa->gen = CYAPA_GEN5;
		cyapa->state = CYAPA_STATE_GEN5_APP;
	} else {
		/* Should not happen!!! */
		cyapa->state = CYAPA_STATE_NO_DEVICE;
	}

	return 0;
}

static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len)
{
	int length;

	if (!reg_data || len < 3)
		return -EINVAL;

	cyapa->state = CYAPA_STATE_NO_DEVICE;

	/* Parse based on Gen5 characteristic registers and bits */
	length = get_unaligned_le16(&reg_data[PIP_RESP_LENGTH_OFFSET]);
	if (length == 0 || length == PIP_RESP_LENGTH_SIZE) {
		gen5_idle_state_parse(cyapa);
	} else if (length == PIP_HID_DESCRIPTOR_SIZE &&
			(reg_data[2] == PIP_HID_BL_REPORT_ID ||
				reg_data[2] == PIP_HID_APP_REPORT_ID)) {
		gen5_hid_description_header_parse(cyapa, reg_data);
	} else if ((length == GEN5_APP_REPORT_DESCRIPTOR_SIZE ||
			length == GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE) &&
			reg_data[2] == GEN5_APP_REPORT_DESCRIPTOR_ID) {
		/* 0xEE 0x00 0xF6 is Gen5 APP report description header. */
		cyapa->gen = CYAPA_GEN5;
		cyapa->state = CYAPA_STATE_GEN5_APP;
	} else if (length == GEN5_BL_REPORT_DESCRIPTOR_SIZE &&
			reg_data[2] == GEN5_BL_REPORT_DESCRIPTOR_ID) {
		/* 0x1D 0x00 0xFE is Gen5 BL report descriptor header. */
		cyapa->gen = CYAPA_GEN5;
		cyapa->state = CYAPA_STATE_GEN5_BL;
	} else if (reg_data[2] == PIP_TOUCH_REPORT_ID ||
			reg_data[2] == PIP_BTN_REPORT_ID ||
			reg_data[2] == GEN5_OLD_PUSH_BTN_REPORT_ID ||
			reg_data[2] == PIP_PUSH_BTN_REPORT_ID ||
			reg_data[2] == PIP_WAKEUP_EVENT_REPORT_ID) {
		gen5_report_data_header_parse(cyapa, reg_data);
	} else if (reg_data[2] == PIP_BL_RESP_REPORT_ID ||
			reg_data[2] == PIP_APP_RESP_REPORT_ID) {
		gen5_cmd_resp_header_parse(cyapa, reg_data);
	}

	if (cyapa->gen == CYAPA_GEN5) {
		/*
		 * Must read the content (e.g.: report description and so on)
		 * from trackpad device throughout. Otherwise,
		 * Gen5 trackpad cannot response to next command or
		 * report any touch or button data later.
		 */
		cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);

		if (cyapa->state == CYAPA_STATE_GEN5_APP ||
			cyapa->state == CYAPA_STATE_GEN5_BL)
			return 0;
	}

	return -EAGAIN;
}

static struct cyapa_tsg_bin_image_data_record *
cyapa_get_image_record_data_num(const struct firmware *fw,
		int *record_num)
{
	int head_size;

	head_size = fw->data[0] + 1;
	*record_num = (fw->size - head_size) /
			sizeof(struct cyapa_tsg_bin_image_data_record);
	return (struct cyapa_tsg_bin_image_data_record *)&fw->data[head_size];
}

int cyapa_pip_bl_initiate(struct cyapa *cyapa, const struct firmware *fw)
{
	struct cyapa_tsg_bin_image_data_record *image_records;
	struct pip_bl_cmd_head *bl_cmd_head;
	struct pip_bl_packet_start *bl_packet_start;
	struct pip_bl_initiate_cmd_data *cmd_data;
	struct pip_bl_packet_end *bl_packet_end;
	u8 cmd[CYAPA_TSG_MAX_CMD_SIZE];
	int cmd_len;
	u16 cmd_data_len;
	u16 cmd_crc = 0;
	u16 meta_data_crc = 0;
	u8 resp_data[11];
	int resp_len;
	int records_num;
	u8 *data;
	int error;

	/* Try to dump all buffered report data before any send command. */
	cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);

	memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE);
	bl_cmd_head = (struct pip_bl_cmd_head *)cmd;
	cmd_data_len = CYAPA_TSG_BL_KEY_SIZE + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE;
	cmd_len = sizeof(struct pip_bl_cmd_head) + cmd_data_len +
		  sizeof(struct pip_bl_packet_end);

	put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &bl_cmd_head->addr);