usb: typec: ucsi: add cmd used for fw flashing
PATCH v3 4/6 usb: typec: ucsi: add cmd used for fw flashing
Quoted 262 lines · Ajay Gupta
From: Ajay Gupta <[email protected]>
Adding support for below commands which will be used during firmware flashing.
-ENTER_FLASHING
- RESET
-PDPORT_ENABLE
-JUMP_TO_BOOT
-FLASH_ROW_RW
-VALIDATE_FW
I command specific mutex lock is also added to sync between driver and user threads.Signed-off-by Ajay Gupta <[email protected]>---
Changes from v2 to v3
- Nonedrivers/usb/typec/ucsi/ucsi_ccg.c | 216 ++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+)drivers/usb/typec/ucsi/ucsi_ccg.c +205
-0@@ -30,13 +30,34 @@ enum enum_fw_mode {#define PORT0_INT BIT(1)#define PORT1_INT BIT(2)#define UCSI_READ_INT BIT(7) +#define CCGX_RAB_JUMP_TO_BOOT 0x0007 +#define TO_BOOT 'J' +#define TO_ALT_FW 'A' +#define CCGX_RAB_RESET_REQ 0x0008 +#define RESET_SIG 'R' +#define CMD_RESET_I2C 0x0 +#define CMD_RESET_DEV 0x1 +#define CCGX_RAB_ENTER_FLASHING 0x000A +#define FLASH_ENTER_SIG 'P' +#define CCGX_RAB_VALIDATE_FW 0x000B +#define CCGX_RAB_FLASH_ROW_RW 0x000C +#define FLASH_SIG 'F' +#define FLASH_RD_CMD 0x0 +#define FLASH_WR_CMD 0x1 +#define FLASH_FWCT1_WR_CMD 0x2 +#define FLASH_FWCT2_WR_CMD 0x3 +#define FLASH_FWCT_SIG_WR_CMD 0x4#define CCGX_RAB_READ_ALL_VER 0x0010#define CCGX_RAB_READ_FW2_VER 0x0020#define CCGX_RAB_UCSI_CONTROL 0x0039#define CCGX_RAB_UCSI_CONTROL_START BIT(0)#define CCGX_RAB_UCSI_CONTROL_STOP BIT(1)#define CCGX_RAB_UCSI_DATA_BLOCK (offset) (0xf000 | ((offset) & 0xff)) +#define REG_FLASH_RW_MEM 0x0200#define DEV_REG_IDX CCGX_RAB_DEVICE_MODE +#define CCGX_RAB_PDPORT_ENABLE 0x002C +#define PDPORT_1 BIT(0) +#define PDPORT_2 BIT(1)#define CCGX_RAB_RESPONSE 0x007E#define ASYNC_EVENT BIT(7)@@ -47,6 +68,13 @@ enum enum_fw_mode {#define PORT_DISCONNECT_DET 0x85#define ROLE_SWAP_COMPELETE 0x87 +/* ccg firmware */ +#define CYACD_LINE_SIZE 527 +#define CCG4_ROW_SIZE 256 +#define FW1_METADATA_ROW 0x1FF +#define FW2_METADATA_ROW 0x1FE +#define FW_CFG_TABLE_SIG_SIZE 256 +struct ccg_dev_info {#define CCG_DEVINFO_FWMODE_SHIFT (0)#define CCG_DEVINFO_FWMODE_MASK (0x3 << CCG_DEVINFO_FWMODE_SHIFT)@@ -118,6 +146,7 @@ struct ucsi_ccg {struct ccg_resp dev_resp;u8 cmd_resp;int port_num; +struct mutex lock;/* to sync between user and driver thread */ };static int ccg_read (struct ucsi_ccg *uc,u16 rab,u8 *data,u32 len)@@ -431,6 +460,193 @@ static int ccg_send_command(struct ucsi_ccg *uc, struct ccg_cmd *cmd)return uc->cmd_resp; } +static int ccg_cmd_enter_flashing (struct ucsi_ccg *uc) +{ +struct ccg_cmd cmd; +int ret; + + cmd.reg =CCGX_RAB_ENTER_FLASHING ; + cmd.data =FLASH_ENTER_SIG ; + cmd.len =1 ; + cmd.delay =50 ; + +mutex_lock (&uc->lock); + + ret =ccg_send_command (uc, &cmd); + +mutex_unlock (&uc->lock); + +if (ret !=CMD_SUCCESS ) { +dev_err (uc->dev,"enter flashing failed ret=%d\n" , ret); +return ret; + } + +return 0 ; +} + +static int ccg_cmd_reset (struct ucsi_ccg *uc,bool extra_delay) +{ +struct ccg_cmd cmd; +u8 *p; +int ret; + + p = (u8 *)&cmd.data; + cmd.reg =CCGX_RAB_RESET_REQ ; + p[0 ] =RESET_SIG ; + p[1 ] =CMD_RESET_DEV ; + cmd.len =2 ; + cmd.delay =2000 + (extra_delay ?3000 :0 ); + +mutex_lock (&uc->lock); + +set_bit (RESET_PENDING , &uc->flags); + + ret =ccg_send_command (uc, &cmd); +if (ret !=RESET_COMPLETE ) + goto err_clear_flag; + + ret =0 ; + +err_clear_flag: +clear_bit (RESET_PENDING , &uc->flags); + +mutex_unlock (&uc->lock); + +return ret; +} + +static int ccg_cmd_port_control (struct ucsi_ccg *uc,bool enable) +{ +struct ccg_cmd cmd; +int ret; + + cmd.reg =CCGX_RAB_PDPORT_ENABLE ; +if (enable) + cmd.data = (uc->port_num ==1 ) ? +PDPORT_1 : (PDPORT_1 |PDPORT_2 ); +else + cmd.data =0x0 ; + cmd.len =1 ; + cmd.delay =10 ; + +mutex_lock (&uc->lock); + + ret =ccg_send_command (uc, &cmd); + +mutex_unlock (&uc->lock); + +if (ret !=CMD_SUCCESS ) { +dev_err (uc->dev,"port control failed ret=%d\n" , ret); +return ret; + } +return 0 ; +} + +static int ccg_cmd_jump_boot_mode (struct ucsi_ccg *uc,int bl_mode) +{ +struct ccg_cmd cmd; +int ret; + + cmd.reg =CCGX_RAB_JUMP_TO_BOOT ; + +if (bl_mode) + cmd.data =TO_BOOT ; +else + cmd.data =TO_ALT_FW ; + + cmd.len =1 ; + cmd.delay =100 ; + +mutex_lock (&uc->lock); + +set_bit (RESET_PENDING , &uc->flags); + + ret =ccg_send_command (uc, &cmd); +if (ret !=RESET_COMPLETE ) + goto err_clear_flag; + + ret =0 ; + +err_clear_flag: +clear_bit (RESET_PENDING , &uc->flags); + +mutex_unlock (&uc->lock); + +return ret; +} + +static int +ccg_cmd_write_flash_row (struct ucsi_ccg *uc,u16 row, +const void *data,u8 fcmd) +{ +struct i2c_client *client = uc->client; +struct ccg_cmd cmd; +u8 buf[CCG4_ROW_SIZE +2 ]; +u8 *p; +int ret; + +/* Copy the data into the flash read/write memory. */ + buf[0 ] =REG_FLASH_RW_MEM &0xFF ; + buf[1 ] =REG_FLASH_RW_MEM >>8 ; + +memcpy (buf +2 , data,CCG4_ROW_SIZE ); + +mutex_lock (&uc->lock); + + ret =i2c_master_send (client, buf,CCG4_ROW_SIZE +2 ); +if (ret !=CCG4_ROW_SIZE +2 ) { +dev_err (uc->dev,"REG_FLASH_RW_MEM write fail %d\n" , ret); +return ret <0 ? ret : -EIO ; + } + +/* Use the FLASH_ROW_READ_WRITE register to trigger */ +/* writing of data to the desired flash row */ + p = (u8 *)&cmd.data; + cmd.reg =CCGX_RAB_FLASH_ROW_RW ; + p[0 ] =FLASH_SIG ; + p[1 ] = fcmd; + p[2 ] = row &0xFF ; + p[3 ] = row >>8 ; + cmd.len =4 ; + cmd.delay =50 ; +if (fcmd ==FLASH_FWCT_SIG_WR_CMD ) + cmd.delay +=400 ; +if (row ==510 ) + cmd.delay +=220 ; + ret =ccg_send_command (uc, &cmd); + +mutex_unlock (&uc->lock); + +if (ret !=CMD_SUCCESS ) { +dev_err (uc->dev,"write flash row failed ret=%d\n" , ret); +return ret; + } + +return 0 ; +} + +static int ccg_cmd_validate_fw (struct ucsi_ccg *uc,unsigned int fwid) +{ +struct ccg_cmd cmd; +int ret; + + cmd.reg =CCGX_RAB_VALIDATE_FW ; + cmd.data = fwid; + cmd.len =1 ; + cmd.delay =500 ; + +mutex_lock (&uc->lock);
drivers/usb/typec/ucsi/ucsi_ccg.c static int ccg_send_command(struct ucsi_ccg *uc, struct ccg_cmd *cmd) · line 648
Quoted 10 lines
drivers/usb/typec/ucsi/ucsi_ccg.c +10
-0+ + ret =ccg_send_command (uc, &cmd); + +mutex_unlock (&uc->lock); + +if (ret !=CMD_SUCCESS ) +return ret; + +return 0 ; +}
Here you finally call ccg_send_command(), but now you introduce new functions that are not yet used, causing compiler warnings.
I think these patches need to be reorganized.
thanks,