On Fri, Feb 01, 2019 at 05:05:08PM -0800, Ajay Gupta wrote:
> From: Ajay Gupta <aj...@nvidia.com>
> 
> 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 <aj...@nvidia.com>
> ---
> Changes from v2 to v3
>       - None
> 
>  drivers/usb/typec/ucsi/ucsi_ccg.c | 216 ++++++++++++++++++++++++++++++
>  1 file changed, 216 insertions(+)
> 
> diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c 
> b/drivers/usb/typec/ucsi/ucsi_ccg.c
> index 63b07b7d17f2..b9bbe90bdf57 100644
> --- a/drivers/usb/typec/ucsi/ucsi_ccg.c
> +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
> @@ -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);
> +
> +     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,

-- 
heikki

Reply via email to