From patchwork Sat Feb 2 01:05:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ajay Gupta X-Patchwork-Id: 10793915 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 19525184E for ; Sat, 2 Feb 2019 01:05:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0AC4C32F9D for ; Sat, 2 Feb 2019 01:05:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F3B9332FA0; Sat, 2 Feb 2019 01:05:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5C22032F9F for ; Sat, 2 Feb 2019 01:05:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727202AbfBBBF0 (ORCPT ); Fri, 1 Feb 2019 20:05:26 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:37274 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727154AbfBBBF0 (ORCPT ); Fri, 1 Feb 2019 20:05:26 -0500 Received: by mail-pl1-f196.google.com with SMTP id b5so4078439plr.4 for ; Fri, 01 Feb 2019 17:05:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6T+VlfYfzQBDVcCATmfdWfBzG/0ZHJEWYZgK0joCQ9I=; b=IrYP+Ob3ieS2nFciwY/Oe51ucN7C4qzNdHFvctb4FQKefA434vbH0KDDhWxRL/4cLl 1gwuQZEbJgbaV1za733JglsxhYVoUELoYVxU8Qx79wVDoXmiWBxELkIVdohKh1O90cFZ jyTU+WnjnEsX5mCBdJriSYj+JW+gj0EaYI9H+TvKyVKGgCD7l5IO0ZCwp+0IuNv+EhKp CpRsMTUjnFnErZZN1C4+7ay+pP+F/8+UrJQrvg8Hw8fZZHo0n1wvjr9upzcmWkT6wYTM UciyXs1NLmcZW12ym41Dw/mCviAerSj6G1LGL8fPBb4E4anRjdEq++DXKg4MS8VrsjEY Wcew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6T+VlfYfzQBDVcCATmfdWfBzG/0ZHJEWYZgK0joCQ9I=; b=k7pRCt0w3DkOISmmtN+e6kaukx7kYdvQaD/aU+yG89gmi4347k2LYvmgYvQ8Uho4b4 P82pZaKCdXaSmgzZue2rIBWGznsuW8/yF3UqmeWc3dvl5iP4keCME/yHiwdKiT7pPjSh Cu7x38uYCy+8O6GFFLKk9IcTbNfedDimh6bFpQtGGDeZBjLwjxn3tzHMd3QEQQ91gVrr dtvqaYZYmsujXY58uzoHGPhPUQc6PuLzy+JiYgjApo+BcSxe4KQQShjad30DcIV8Fqba IWVAKWjzy+sLcxLeDv3grSV/YA6JzvCELHR4vxJ/ILAhjROwgLRTjud5RdLNYAtcOlrs WfcQ== X-Gm-Message-State: AJcUukeiCPqVg9p1nQ09VJzHyP7tjRmlVi6STiiSWxNBcZxdTDS9UW/v m5xcgJEPAyRGLC+tr9Jt6V8= X-Google-Smtp-Source: ALg8bN5FGN4Iu5fEZokfWLz/uKn2YJ0N5RJKWth8ZQm3ZU3nAeupvto6g7x308R11m/BvhIskbbT2A== X-Received: by 2002:a17:902:850c:: with SMTP id bj12mr41238228plb.46.1549069525264; Fri, 01 Feb 2019 17:05:25 -0800 (PST) Received: from ajayg.nvidia.com (searspoint.nvidia.com. [216.228.112.21]) by smtp.gmail.com with ESMTPSA id f6sm13158685pfg.188.2019.02.01.17.05.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 01 Feb 2019 17:05:24 -0800 (PST) From: Ajay Gupta X-Google-Original-From: Ajay Gupta To: heikki.krogerus@linux.intel.com Cc: linux-usb@vger.kernel.org, Ajay Gupta Subject: [PATCH v3 4/6] usb: typec: ucsi: add cmd used for fw flashing Date: Fri, 1 Feb 2019 17:05:08 -0800 Message-Id: <20190202010510.25016-5-ajayg@nvidia.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190202010510.25016-1-ajayg@nvidia.com> References: <20190202010510.25016-1-ajayg@nvidia.com> X-NVConfidentiality: public Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Ajay Gupta 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 --- 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; +} + static int ucsi_ccg_probe(struct i2c_client *client, const struct i2c_device_id *id) {