|
17 | 17 | #include <asm/unaligned.h>
|
18 | 18 | #include "ucsi.h"
|
19 | 19 |
|
| 20 | +enum enum_fw_mode { |
| 21 | + BOOT, /* bootloader */ |
| 22 | + FW1, /* FW partition-1 (contains secondary fw) */ |
| 23 | + FW2, /* FW partition-2 (contains primary fw) */ |
| 24 | + FW_INVALID, |
| 25 | +}; |
| 26 | + |
| 27 | +struct ccg_dev_info { |
| 28 | +#define CCG_DEVINFO_FWMODE_SHIFT (0) |
| 29 | +#define CCG_DEVINFO_FWMODE_MASK (0x3 << CCG_DEVINFO_FWMODE_SHIFT) |
| 30 | +#define CCG_DEVINFO_PDPORTS_SHIFT (2) |
| 31 | +#define CCG_DEVINFO_PDPORTS_MASK (0x3 << CCG_DEVINFO_PDPORTS_SHIFT) |
| 32 | + u8 mode; |
| 33 | + u8 bl_mode; |
| 34 | + __le16 silicon_id; |
| 35 | + __le16 bl_last_row; |
| 36 | +} __packed; |
| 37 | + |
| 38 | +struct version_format { |
| 39 | + __le16 build; |
| 40 | + u8 patch; |
| 41 | + u8 ver; |
| 42 | +#define CCG_VERSION_MIN_SHIFT (0) |
| 43 | +#define CCG_VERSION_MIN_MASK (0xf << CCG_VERSION_MIN_SHIFT) |
| 44 | +#define CCG_VERSION_MAJ_SHIFT (4) |
| 45 | +#define CCG_VERSION_MAJ_MASK (0xf << CCG_VERSION_MAJ_SHIFT) |
| 46 | +} __packed; |
| 47 | + |
| 48 | +struct version_info { |
| 49 | + struct version_format base; |
| 50 | + struct version_format app; |
| 51 | +}; |
| 52 | + |
20 | 53 | struct ucsi_ccg {
|
21 | 54 | struct device *dev;
|
22 | 55 | struct ucsi *ucsi;
|
23 | 56 | struct ucsi_ppm ppm;
|
24 | 57 | struct i2c_client *client;
|
| 58 | + struct ccg_dev_info info; |
| 59 | + /* version info for boot, primary and secondary */ |
| 60 | + struct version_info version[FW2 + 1]; |
25 | 61 | };
|
26 | 62 |
|
27 |
| -#define CCGX_RAB_INTR_REG 0x06 |
28 |
| -#define CCGX_RAB_UCSI_CONTROL 0x39 |
| 63 | +#define CCGX_RAB_DEVICE_MODE 0x0000 |
| 64 | +#define CCGX_RAB_INTR_REG 0x0006 |
| 65 | +#define CCGX_RAB_READ_ALL_VER 0x0010 |
| 66 | +#define CCGX_RAB_READ_FW2_VER 0x0020 |
| 67 | +#define CCGX_RAB_UCSI_CONTROL 0x0039 |
29 | 68 | #define CCGX_RAB_UCSI_CONTROL_START BIT(0)
|
30 | 69 | #define CCGX_RAB_UCSI_CONTROL_STOP BIT(1)
|
31 | 70 | #define CCGX_RAB_UCSI_DATA_BLOCK(offset) (0xf000 | ((offset) & 0xff))
|
@@ -220,6 +259,23 @@ static irqreturn_t ccg_irq_handler(int irq, void *data)
|
220 | 259 | return IRQ_HANDLED;
|
221 | 260 | }
|
222 | 261 |
|
| 262 | +static int get_fw_info(struct ucsi_ccg *uc) |
| 263 | +{ |
| 264 | + int err; |
| 265 | + |
| 266 | + err = ccg_read(uc, CCGX_RAB_READ_ALL_VER, (u8 *)(&uc->version), |
| 267 | + sizeof(uc->version)); |
| 268 | + if (err < 0) |
| 269 | + return err; |
| 270 | + |
| 271 | + err = ccg_read(uc, CCGX_RAB_DEVICE_MODE, (u8 *)(&uc->info), |
| 272 | + sizeof(uc->info)); |
| 273 | + if (err < 0) |
| 274 | + return err; |
| 275 | + |
| 276 | + return 0; |
| 277 | +} |
| 278 | + |
223 | 279 | static int ucsi_ccg_probe(struct i2c_client *client,
|
224 | 280 | const struct i2c_device_id *id)
|
225 | 281 | {
|
@@ -248,6 +304,12 @@ static int ucsi_ccg_probe(struct i2c_client *client,
|
248 | 304 | return status;
|
249 | 305 | }
|
250 | 306 |
|
| 307 | + status = get_fw_info(uc); |
| 308 | + if (status < 0) { |
| 309 | + dev_err(uc->dev, "get_fw_info failed - %d\n", status); |
| 310 | + return status; |
| 311 | + } |
| 312 | + |
251 | 313 | status = devm_request_threaded_irq(dev, client->irq, NULL,
|
252 | 314 | ccg_irq_handler,
|
253 | 315 | IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
|
|
0 commit comments