usb: typec: ucsi: ccg: add get_fw_info function

Function is to get the details of ccg firmware and device version.
It will be useful in debugging and also during firmware update.

Signed-off-by: Ajay Gupta <ajayg@nvidia.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ajay Gupta 2019-04-23 17:21:45 +03:00 committed by Greg Kroah-Hartman
parent 6e3c8beb4f
commit 5d438e2002

View File

@ -17,15 +17,54 @@
#include <asm/unaligned.h>
#include "ucsi.h"
enum enum_fw_mode {
BOOT, /* bootloader */
FW1, /* FW partition-1 (contains secondary fw) */
FW2, /* FW partition-2 (contains primary fw) */
FW_INVALID,
};
struct ccg_dev_info {
#define CCG_DEVINFO_FWMODE_SHIFT (0)
#define CCG_DEVINFO_FWMODE_MASK (0x3 << CCG_DEVINFO_FWMODE_SHIFT)
#define CCG_DEVINFO_PDPORTS_SHIFT (2)
#define CCG_DEVINFO_PDPORTS_MASK (0x3 << CCG_DEVINFO_PDPORTS_SHIFT)
u8 mode;
u8 bl_mode;
__le16 silicon_id;
__le16 bl_last_row;
} __packed;
struct version_format {
__le16 build;
u8 patch;
u8 ver;
#define CCG_VERSION_MIN_SHIFT (0)
#define CCG_VERSION_MIN_MASK (0xf << CCG_VERSION_MIN_SHIFT)
#define CCG_VERSION_MAJ_SHIFT (4)
#define CCG_VERSION_MAJ_MASK (0xf << CCG_VERSION_MAJ_SHIFT)
} __packed;
struct version_info {
struct version_format base;
struct version_format app;
};
struct ucsi_ccg {
struct device *dev;
struct ucsi *ucsi;
struct ucsi_ppm ppm;
struct i2c_client *client;
struct ccg_dev_info info;
/* version info for boot, primary and secondary */
struct version_info version[FW2 + 1];
};
#define CCGX_RAB_INTR_REG 0x06
#define CCGX_RAB_UCSI_CONTROL 0x39
#define CCGX_RAB_DEVICE_MODE 0x0000
#define CCGX_RAB_INTR_REG 0x0006
#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))
@ -220,6 +259,23 @@ static irqreturn_t ccg_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
static int get_fw_info(struct ucsi_ccg *uc)
{
int err;
err = ccg_read(uc, CCGX_RAB_READ_ALL_VER, (u8 *)(&uc->version),
sizeof(uc->version));
if (err < 0)
return err;
err = ccg_read(uc, CCGX_RAB_DEVICE_MODE, (u8 *)(&uc->info),
sizeof(uc->info));
if (err < 0)
return err;
return 0;
}
static int ucsi_ccg_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@ -248,6 +304,12 @@ static int ucsi_ccg_probe(struct i2c_client *client,
return status;
}
status = get_fw_info(uc);
if (status < 0) {
dev_err(uc->dev, "get_fw_info failed - %d\n", status);
return status;
}
status = devm_request_threaded_irq(dev, client->irq, NULL,
ccg_irq_handler,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH,