aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFalong Li2020-01-20 00:17:04 -0600
committerFalong Li2020-01-20 00:17:04 -0600
commita7b3ff61409623a308c0d1acb1d8da98b1356512 (patch)
tree895ab2e922fe0562d2b402127611cbb130434452
parent4fa386e339f62dff273bb2ba24c7265486d634ae (diff)
downloadbms-kernel-4-4-a7b3ff61409623a308c0d1acb1d8da98b1356512.tar.gz
bms-kernel-4-4-a7b3ff61409623a308c0d1acb1d8da98b1356512.tar.xz
bms-kernel-4-4-a7b3ff61409623a308c0d1acb1d8da98b1356512.zip
add bq27426 driver
-rw-r--r--drivers/power/Kconfig1
-rw-r--r--drivers/power/Makefile5
-rw-r--r--drivers/power/bq27426/Kconfig6
-rw-r--r--drivers/power/bq27426/Makefile1
-rw-r--r--drivers/power/bq27426/bq27426_fg.c2005
-rw-r--r--drivers/power/bq27426/bq27426_gmfs_coslight.h945
-rw-r--r--drivers/power/bq27426/bqfs_cmd_type.h42
7 files changed, 3003 insertions, 2 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 59881a83ac8b..987e6176f77a 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -523,6 +523,7 @@ source "drivers/power/bq28z610/Kconfig"
523source "drivers/power/bq34z100/Kconfig" 523source "drivers/power/bq34z100/Kconfig"
524source "drivers/power/bq2560x/Kconfig" 524source "drivers/power/bq2560x/Kconfig"
525source "drivers/power/bq24725a/Kconfig" 525source "drivers/power/bq24725a/Kconfig"
526source "drivers/power/bq27426/Kconfig"
526 527
527endif # POWER_SUPPLY 528endif # POWER_SUPPLY
528 529
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index d9023c9e16de..3b3ad1876ed1 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -74,7 +74,7 @@ obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
74obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o 74obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o
75obj-y += bq25600-slave/ 75obj-y += bq25600-slave/
76obj-y += bq25606-slave/ 76obj-y += bq25606-slave/
77obj-y += bq25910-slave/ 77#obj-y += bq25910-slave/
78obj-y += bq27z860/ 78obj-y += bq27z860/
79obj-y += bq27532/ 79obj-y += bq27532/
80obj-y += bq27z561/ 80obj-y += bq27z561/
@@ -85,6 +85,7 @@ obj-y += bq40z50/
85#obj-y += bq2429x/ 85#obj-y += bq2429x/
86obj-y += bq28z610/ 86obj-y += bq28z610/
87obj-y += bq34z100/ 87obj-y += bq34z100/
88obj-y += bq2560x/ 88#obj-y += bq2560x/
89obj-y += bq24725a/ 89obj-y += bq24725a/
90obj-y += bq27426/
90 91
diff --git a/drivers/power/bq27426/Kconfig b/drivers/power/bq27426/Kconfig
new file mode 100644
index 000000000000..538c1382e373
--- /dev/null
+++ b/drivers/power/bq27426/Kconfig
@@ -0,0 +1,6 @@
1config FUEL_GAUGE_BQ27426
2 tristate "TI bq27426 battery gauge driver"
3 depends on I2C
4 default y
5 help
6 Say Y to enable support for TI bq27426 fuel gauge driver
diff --git a/drivers/power/bq27426/Makefile b/drivers/power/bq27426/Makefile
new file mode 100644
index 000000000000..247bba2694f3
--- /dev/null
+++ b/drivers/power/bq27426/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_FUEL_GAUGE_BQ27426) += bq27426_fg.o
diff --git a/drivers/power/bq27426/bq27426_fg.c b/drivers/power/bq27426/bq27426_fg.c
new file mode 100644
index 000000000000..ec7b8555d01b
--- /dev/null
+++ b/drivers/power/bq27426/bq27426_fg.c
@@ -0,0 +1,2005 @@
1/*
2 * bqGauge battery driver
3 *
4 * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
5 * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
6 * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de>
7 * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com>
8 *
9 * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
10 *
11 * This package is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 */
20
21/*
22 * Datasheets:
23 */
24#define pr_fmt(fmt) "bq27426- %s: " fmt, __func__
25#include <linux/module.h>
26#include <linux/param.h>
27#include <linux/jiffies.h>
28#include <linux/workqueue.h>
29#include <linux/delay.h>
30#include <linux/platform_device.h>
31#include <linux/power_supply.h>
32#include <linux/idr.h>
33#include <linux/i2c.h>
34#include <linux/slab.h>
35#include <linux/acpi.h>
36#include <asm/unaligned.h>
37#include <linux/uaccess.h>
38#include <linux/interrupt.h>
39#include <linux/gpio/consumer.h>
40#include <linux/debugfs.h>
41#include <linux/alarmtimer.h>
42#include "bqfs_cmd_type.h"
43//#include "bq27426_gmfs.h"
44#include "bq27426_gmfs_coslight.h"
45
46#if 1
47#undef pr_debug
48#define pr_debug pr_err
49#undef pr_info
50#define pr_info pr_err
51#undef dev_dbg
52#define dev_dbg dev_err
53#else
54#undef pr_info
55#define pr_info pr_debug
56#endif
57
58#define MONITOR_ALARM_CHECK_NS 5000000000
59#define INVALID_REG_ADDR 0xFF
60#define BQFS_UPDATE_KEY 0x8F91
61
62
63#define FG_FLAGS_OT BIT(15)
64#define FG_FLAGS_UT BIT(14)
65#define FG_FLAGS_FC BIT(9)
66#define FG_FLAGS_CHG BIT(8)
67#define FG_FLAGS_OCVTAKEN BIT(7)
68#define FG_FLAGS_ITPOR BIT(5)
69#define FG_FLAGS_CFGUPMODE BIT(4)
70#define FG_FLAGS_BAT_DET BIT(3)
71#define FG_FLAGS_SOC1 BIT(2)
72#define FG_FLAGS_SOCF BIT(1)
73#define FG_FLAGS_DSG BIT(0)
74
75
76enum bq_fg_reg_idx {
77 BQ_FG_REG_CTRL = 0,
78 BQ_FG_REG_TEMP, /* Battery Temperature */
79 BQ_FG_REG_VOLT, /* Battery Voltage */
80 BQ_FG_REG_AI, /* Average Current */
81 BQ_FG_REG_FLAGS, /* Flags */
82 BQ_FG_REG_TTE, /* Time to Empty */
83 BQ_FG_REG_TTF, /* Time to Full */
84 BQ_FG_REG_FCC, /* Full Charge Capacity */
85 BQ_FG_REG_RM, /* Remaining Capacity */
86 BQ_FG_REG_CC, /* Cycle Count */
87 BQ_FG_REG_SOC, /* Relative State of Charge */
88 BQ_FG_REG_SOH, /* State of Health */
89 BQ_FG_REG_DC, /* Design Capacity */
90
91 NUM_REGS,
92};
93
94enum bq_fg_subcmd {
95 FG_SUBCMD_CTRL_STATUS = 0x0000,
96 FG_SUBCMD_PART_NUM = 0x0001,
97 FG_SUBCMD_FW_VER = 0x0002,
98 FG_SUBCMD_DM_CODE = 0x0004,
99 FG_SUBCMD_CHEM_ID = 0x0008,
100 FG_SUBCMD_BAT_INSERT = 0x000C,
101 FG_SUBCMD_BAT_REMOVE = 0x000D,
102 FG_SUBCMD_SET_CFGUPDATE = 0x0013,
103 FG_SUBCMD_SEAL = 0x0020,
104 FG_SUBCMD_PULSE_SOC_INT = 0x0023,
105 FG_SUBCMD_CHEM_A = 0x0030,
106 FG_SUBCMD_CHEM_B = 0x0031,
107 FG_SUBCMD_CHEM_C = 0x0032,
108 FG_SUBCMD_SOFT_RESET = 0x0042,
109 FG_SUBCMD_EXIT_CFGMODE = 0x0043,
110};
111
112
113enum {
114 SEAL_STATE_FA,
115 SEAL_STATE_UNSEALED,
116 SEAL_STATE_SEALED,
117};
118
119
120enum bq_fg_device {
121 BQ27X00,
122 BQ27426,
123};
124
125enum {
126 UPDATE_REASON_FG_RESET = 1,
127 UPDATE_REASON_NEW_VERSION,
128 UPDATE_REASON_FORCED,
129};
130
131struct fg_batt_profile {
132 const bqfs_cmd_t * bqfs_image;
133 u32 array_size;
134 u8 version;
135};
136
137static const struct fg_batt_profile bqfs_image[] = {
138 { bqfs_coslight, ARRAY_SIZE(bqfs_coslight), 1 },//100
139 /* Add more entries if multiple batteries are supported */
140
141};
142
143static const unsigned char *device2str[] = {
144 "bq27x00",
145 "bq27426",
146};
147
148static const unsigned char *update_reason_str[] = {
149 "Reset",
150 "New Version",
151 "Force"
152};
153
154static u8 bq27426_regs[NUM_REGS] = {
155 0x00, /* CONTROL */
156 0x02, /* TEMP */
157 0x04, /* VOLT */
158 0x10, /* AVG CURRENT */
159 0x06, /* FLAGS */
160 0xFF, /* Time to empty */
161 0xFF, /* Time to full */
162 0x0E, /* Full charge capacity */
163 0x0C, /* Remaining Capacity */
164 0xFF, /* CycleCount */
165 0x1C, /* State of Charge */
166 0x20, /* State of Health */
167 0xFF, /* Design Capacity */
168};
169
170struct bq_fg_chip;
171
172struct bq_fg_chip {
173 struct device *dev;
174 struct i2c_client *client;
175
176
177 struct mutex i2c_rw_lock;
178 struct mutex data_lock;
179 struct mutex update_lock;
180 struct mutex irq_complete;
181
182 bool irq_waiting;
183 bool irq_disabled;
184 bool resume_completed;
185
186 int force_update;
187 int fw_ver;
188 int df_ver;
189
190 u8 chip;
191 u8 regs[NUM_REGS];
192
193 int batt_id;
194
195 /* status tracking */
196
197 bool batt_present;
198 bool batt_fc;
199 bool batt_ot;
200 bool batt_ut;
201 bool batt_soc1;
202 bool batt_socf;
203 bool batt_dsg;
204 bool allow_chg;
205 bool cfg_update_mode;
206 bool itpor;
207
208 int seal_state; /* 0 - Full Access, 1 - Unsealed, 2 - Sealed */
209 int batt_tte;
210 int batt_soc;
211 int batt_fcc; /* Full charge capacity */
212 int batt_rm; /* Remaining capacity */
213 int batt_dc; /* Design Capacity */
214 int batt_volt;
215 int batt_temp;
216 int batt_curr;
217
218 int batt_cyclecnt; /* cycle count */
219
220
221 struct work_struct update_work;
222
223 unsigned long last_update;
224
225 /* debug */
226 int skip_reads;
227 int skip_writes;
228
229 int fake_soc;
230 int fake_temp;
231
232 struct dentry *debug_root;
233
234 struct power_supply *fg_psy;
235 struct power_supply_desc fg_psy_d;
236};
237
238
239
240static int __fg_read_byte(struct i2c_client *client, u8 reg, u8 *val)
241{
242 s32 ret;
243
244 ret = i2c_smbus_read_byte_data(client, reg);
245 if (ret < 0) {
246 pr_err("i2c read byte fail: can't read from reg 0x%02X\n", reg);
247 return ret;
248 }
249
250 *val = (u8)ret;
251
252 return 0;
253}
254
255static int __fg_write_byte(struct i2c_client *client, u8 reg, u8 val)
256{
257 s32 ret;
258
259 ret = i2c_smbus_write_byte_data(client, reg, val);
260 if (ret < 0) {
261 pr_err("i2c write byte fail: can't write 0x%02X to reg 0x%02X\n",
262 val, reg);
263 return ret;
264 }
265
266 return 0;
267}
268
269
270static int __fg_read_word(struct i2c_client *client, u8 reg, u16 *val)
271{
272 s32 ret;
273
274 ret = i2c_smbus_read_word_data(client, reg);
275 if (ret < 0) {
276 pr_err("i2c read word fail: can't read from reg 0x%02X\n", reg);
277 return ret;
278 }
279
280 *val = (u16)ret;
281
282 return 0;
283}
284
285
286static int __fg_write_word(struct i2c_client *client, u8 reg, u16 val)
287{
288 s32 ret;
289
290 ret = i2c_smbus_write_word_data(client, reg, val);
291 if (ret < 0) {
292 pr_err("i2c write word fail: can't write 0x%02X to reg 0x%02X\n",
293 val, reg);
294 return ret;
295 }
296
297 return 0;
298}
299
300static int __fg_read_block(struct i2c_client *client, u8 reg, u8 *buf, u8 len)
301{
302 int ret;
303 struct i2c_msg msg[2];
304 int i;
305
306 msg[0].addr = client->addr;
307 msg[0].flags = 0;
308 msg[0].buf = &reg;
309 msg[0].len = 1;
310
311 msg[1].addr = client->addr;
312 msg[1].flags = I2C_M_RD;
313 msg[1].buf = buf;
314 msg[1].len = len;
315
316 for (i = 0; i < 3; i++) {
317 ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
318 if (ret >= 0)
319 return ret;
320 else
321 msleep(5);
322 }
323 return ret;
324}
325
326static int __fg_write_block(struct i2c_client *client, u8 reg, u8 *buf, u8 len)
327{
328 int ret;
329 struct i2c_msg msg;
330 u8 data[64];
331 int i = 0;
332
333 data[0] = reg;
334 memcpy(&data[1], buf, len);
335
336 msg.addr = client->addr;
337 msg.flags = 0;
338 msg.buf = data;
339 msg.len = len + 1;
340
341 for (i = 0; i < 3; i++) {
342 ret = i2c_transfer(client->adapter, &msg, 1);
343 if (ret >= 0)
344 return ret;
345 else
346 msleep(5);
347 }
348 return ret;
349}
350
351
352static int fg_read_byte(struct bq_fg_chip *bq, u8 reg, u8 *val)
353{
354 int ret;
355
356 if (bq->skip_reads) {
357 *val = 0;
358 return 0;
359 }
360
361 mutex_lock(&bq->i2c_rw_lock);
362 ret = __fg_read_byte(bq->client, reg, val);
363 mutex_unlock(&bq->i2c_rw_lock);
364
365 return ret;
366}
367
368static int fg_write_byte(struct bq_fg_chip *bq, u8 reg, u8 val)
369{
370 int ret;
371
372 if (bq->skip_writes)
373 return 0;
374
375 mutex_lock(&bq->i2c_rw_lock);
376 ret = __fg_write_byte(bq->client, reg, val);
377 mutex_unlock(&bq->i2c_rw_lock);
378
379 return ret;
380}
381
382static int fg_read_word(struct bq_fg_chip *bq, u8 reg, u16 *val)
383{
384 int ret;
385
386 if (bq->skip_reads) {
387 *val = 0;
388 return 0;
389 }
390
391 mutex_lock(&bq->i2c_rw_lock);
392 ret = __fg_read_word(bq->client, reg, val);
393 mutex_unlock(&bq->i2c_rw_lock);
394
395 return ret;
396}
397
398static int fg_write_word(struct bq_fg_chip *bq, u8 reg, u16 val)
399{
400 int ret;
401
402 if (bq->skip_writes)
403 return 0;
404
405 mutex_lock(&bq->i2c_rw_lock);
406 ret = __fg_write_word(bq->client, reg, val);
407 mutex_unlock(&bq->i2c_rw_lock);
408
409 return ret;
410}
411
412static int fg_read_block(struct bq_fg_chip *bq, u8 reg, u8 *buf, u8 len)
413{
414 int ret;
415
416 if (bq->skip_reads)
417 return 0;
418 mutex_lock(&bq->i2c_rw_lock);
419 ret = __fg_read_block(bq->client, reg, buf, len);
420 mutex_unlock(&bq->i2c_rw_lock);
421
422 return ret;
423
424}
425
426static int fg_write_block(struct bq_fg_chip *bq, u8 reg, u8 *data, u8 len)
427{
428 int ret;
429
430 if (bq->skip_writes)
431 return 0;
432
433 mutex_lock(&bq->i2c_rw_lock);
434 ret = __fg_write_block(bq->client, reg, data, len);
435 mutex_unlock(&bq->i2c_rw_lock);
436
437 return ret;
438}
439
440#define CTRL_REG 0x00
441
442#define FG_DFT_UNSEAL_KEY1 0x80008000
443#define FG_DFT_UNSEAL_KEY2 0x36724614
444
445#define FG_DFT_UNSEAL_FA_KEY 0xFFFFFFFF
446
447static u8 checksum(u8 *data, u8 len)
448{
449 u8 i;
450 u16 sum = 0;
451
452 for (i = 0; i < len; i++)
453 sum += data[i];
454
455 sum &= 0xFF;
456
457 return (0xFF - sum);
458}
459
460#if 0
461static void fg_print_buf(const char *msg, u8 *buf, u8 len)
462{
463 int i;
464 int idx = 0;
465 int num;
466 u8 strbuf[128];
467
468 pr_err("%s buf: ", msg);
469 for(i = 0; i < len; i++) {
470 num = sprintf(&strbuf[idx], "%02X ", buf[i]);
471 idx += num;
472 }
473 pr_err("%s\n", strbuf);
474}
475#else
476static void fg_print_buf(const char *msg, u8 *buf, u8 len)
477{}
478#endif
479
480
481#define TIMEOUT_INIT_COMPLETED 100
482static int fg_check_init_completed(struct bq_fg_chip *bq)
483{
484 int ret;
485 int i = 0;
486 u16 status;
487
488 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], FG_SUBCMD_CTRL_STATUS);
489 if (ret < 0) {
490 pr_err("Failed to write control status cmd, ret = %d\n", ret);
491 return ret;
492 }
493
494 msleep(5);
495
496 while (i++ < TIMEOUT_INIT_COMPLETED) {
497 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_CTRL], &status);
498 if (ret >= 0 && (status & 0x0080))
499 return 0;
500 msleep(100);
501 }
502 pr_err("wait for FG INITCOMP timeout\n");
503 return ret;
504}
505
506static int fg_get_seal_state(struct bq_fg_chip *bq)
507{
508 int ret;
509 u16 status;
510
511 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], FG_SUBCMD_CTRL_STATUS);
512 if (ret < 0) {
513 pr_err("Failed to write control status cmd, ret = %d\n", ret);
514 return ret;
515 }
516
517 msleep(5);
518
519 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_CTRL], &status);
520 if (ret < 0) {
521 pr_err("Failed to read control status, ret = %d\n", ret);
522 return ret;
523 }
524 pr_err("control_status = 0x%04X", status);
525 if (status & 0x2000)
526 bq->seal_state = SEAL_STATE_SEALED;
527 else
528 bq->seal_state = SEAL_STATE_UNSEALED;
529
530 return 0;
531}
532
533static int fg_unseal(struct bq_fg_chip *bq, u32 key)
534{
535 int ret;
536 int retry = 0;
537
538 ret = fg_get_seal_state(bq);
539 if (ret)
540 return ret;
541 if (bq->seal_state == SEAL_STATE_UNSEALED)
542 return 0;
543
544 pr_info(":key - 0x%08X\n", key);
545
546 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], key & 0xFFFF);
547 if (ret < 0) {
548 pr_err("unable to write unseal key step 1, ret = %d\n", ret);
549 return ret;
550 }
551
552 msleep(5);
553
554 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], (key >> 16) & 0xFFFF);
555 if (ret < 0) {
556 pr_err("unable to write unseal key step 2, ret = %d\n", ret);
557 return ret;
558 }
559
560 msleep(5);
561
562 while (retry++ < 1000) {
563 fg_get_seal_state(bq);
564 if (bq->seal_state == SEAL_STATE_UNSEALED) {
565 return 0;
566 }
567 msleep(100);
568 }
569
570 return -1;
571}
572
573#if 0
574static int fg_unseal_fa(struct bq_fg_chip *bq, u32 key)
575{
576 int ret;
577 int retry = 0;
578
579 pr_info(":key - %d\n", key);
580
581 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], key & 0xFFFF);
582 if (ret < 0) {
583 pr_err("unable to write unseal key step 1, ret = %d\n", ret);
584 return ret;
585 }
586
587 msleep(5);
588
589 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], (key >> 16) & 0xFFFF);
590 if (ret < 0) {
591 pr_err("unable to write unseal key step 2, ret = %d\n", ret);
592 return ret;
593 }
594
595 msleep(5);
596
597 while (retry++ < 1000) {
598 fg_get_seal_state(bq);
599 if (bq->seal_state == SEAL_STATE_FA) {
600 return 0;
601 }
602 msleep(10);
603 }
604
605 return -1;
606}
607EXPORT_SYMBOL_GPL(fg_unseal_fa);
608#endif
609
610static int fg_seal(struct bq_fg_chip *bq)
611{
612 int ret;
613 int retry = 0;
614
615 fg_get_seal_state(bq);
616
617 if (bq->seal_state == SEAL_STATE_SEALED)
618 return 0;
619 msleep(5);
620 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], FG_SUBCMD_SEAL);
621
622 if (ret < 0) {
623 pr_err("Failed to send seal command\n");
624 return ret;
625 }
626
627 while (retry++ < 1000) {
628 fg_get_seal_state(bq);
629 if (bq->seal_state == SEAL_STATE_SEALED)
630 return 0;
631 msleep(200);
632 }
633
634 return -1;
635}
636
637
638
639static int fg_check_cfg_update_mode(struct bq_fg_chip *bq)
640{
641 int ret;
642 u16 flags;
643
644 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_FLAGS], &flags);
645 if (ret < 0) {
646 return ret;
647 }
648
649 bq->cfg_update_mode = !!(flags & FG_FLAGS_CFGUPMODE);
650
651 return 0;
652
653}
654
655static int fg_check_itpor(struct bq_fg_chip *bq)
656{
657 int ret;
658 u16 flags;
659
660 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_FLAGS], &flags);
661 if (ret < 0) {
662 return ret;
663 }
664
665 bq->itpor = !!(flags & FG_FLAGS_ITPOR);
666
667 return 0;
668}
669
670
671static int fg_read_dm_version(struct bq_fg_chip* bq, u8 *ver)
672{
673 int ret;
674 u16 dm_code = 0;
675
676 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], FG_SUBCMD_DM_CODE);
677 if (ret < 0) {
678 pr_err("Failed to write control status cmd, ret = %d\n", ret);
679 return ret;
680 }
681
682 msleep(5);
683
684 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_CTRL], &dm_code);
685 if (!ret)
686 *ver = dm_code & 0xFF;
687 return ret;
688}
689
690#define CFG_UPDATE_POLLING_RETRY_LIMIT 50
691static int fg_dm_pre_access(struct bq_fg_chip *bq)
692{
693 int ret;
694 int i = 0;
695
696 ret = fg_check_init_completed(bq);
697 if (ret < 0)
698 return ret;
699 ret = fg_unseal(bq, FG_DFT_UNSEAL_KEY1);
700 if (ret < 0)
701 return ret;
702
703 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], FG_SUBCMD_SET_CFGUPDATE);
704 if (ret < 0)
705 return ret;
706
707 msleep(10);
708
709 while(i++ < CFG_UPDATE_POLLING_RETRY_LIMIT) {
710 ret = fg_check_cfg_update_mode(bq);
711 if (!ret && bq->cfg_update_mode)
712 return 0;
713 msleep(400);
714 }
715
716 pr_err("Failed to enter cfgupdate mode\n");
717
718 return -1;
719}
720EXPORT_SYMBOL_GPL(fg_dm_pre_access);
721
722static int fg_dm_post_access(struct bq_fg_chip *bq)
723{
724 int ret;
725 int i = 0;
726
727
728 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL],
729 FG_SUBCMD_SOFT_RESET);
730 if (ret < 0)
731 return ret;
732
733 msleep(100);
734
735 while(i++ < CFG_UPDATE_POLLING_RETRY_LIMIT) {
736 ret = fg_check_cfg_update_mode(bq);
737 if (!ret && !bq->cfg_update_mode)
738 break;
739 msleep(100);
740 }
741
742 if (i == CFG_UPDATE_POLLING_RETRY_LIMIT) {
743 pr_err("Failed to exit cfgupdate mode\n");
744 return -1;
745 } else {
746 return fg_seal(bq);
747 }
748}
749EXPORT_SYMBOL_GPL(fg_dm_post_access);
750
751static int fg_dm_enter_cfg_mode(struct bq_fg_chip *bq)
752{
753 return fg_dm_pre_access(bq);
754}
755
756static int fg_dm_exit_cfg_mode(struct bq_fg_chip *bq)
757{
758 int ret;
759 int i = 0;
760
761
762 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL],
763 FG_SUBCMD_EXIT_CFGMODE);
764 if (ret < 0)
765 return ret;
766
767 msleep(100);
768
769 while(i++ < CFG_UPDATE_POLLING_RETRY_LIMIT) {
770 ret = fg_check_cfg_update_mode(bq);
771 if (!ret && !bq->cfg_update_mode)
772 break;
773 msleep(100);
774 }
775
776 if (i == CFG_UPDATE_POLLING_RETRY_LIMIT) {
777 pr_err("Failed to exit cfgupdate mode\n");
778 return -1;
779 } else {
780 return fg_seal(bq);
781 }
782}
783EXPORT_SYMBOL_GPL(fg_dm_exit_cfg_mode);
784
785
786
787#define DM_ACCESS_BLOCK_DATA_CHKSUM 0x60
788#define DM_ACCESS_BLOCK_DATA_CTRL 0x61
789#define DM_ACCESS_BLOCK_DATA_CLASS 0x3E
790#define DM_ACCESS_DATA_BLOCK 0x3F
791#define DM_ACCESS_BLOCK_DATA 0x40
792
793
794static int fg_dm_read_block(struct bq_fg_chip *bq, u8 classid,
795 u8 offset, u8 *buf)
796{
797 int ret;
798 u8 cksum_calc, cksum;
799 u8 blk_offset = offset >> 5;
800
801 pr_info("subclass:%d, offset:%d\n", classid, offset);
802
803 ret = fg_write_byte(bq, DM_ACCESS_BLOCK_DATA_CTRL, 0);
804 if (ret < 0)
805 return ret;
806 msleep(5);
807 ret = fg_write_byte(bq, DM_ACCESS_BLOCK_DATA_CLASS, classid);
808 if (ret < 0)
809 return ret;
810 msleep(5);
811 ret = fg_write_byte(bq, DM_ACCESS_DATA_BLOCK, blk_offset);
812 if (ret < 0)
813 return ret;
814 msleep(5);
815 ret = fg_read_block(bq, DM_ACCESS_BLOCK_DATA, buf, 32);
816 if (ret < 0)
817 return ret;
818
819 fg_print_buf(__func__, buf, 32);
820
821 msleep(5);
822 cksum_calc = checksum(buf, 32);
823 ret = fg_read_byte(bq, DM_ACCESS_BLOCK_DATA_CHKSUM, &cksum);
824 if (!ret && cksum_calc == cksum)
825 return 0;
826 else
827 return 1;
828}
829EXPORT_SYMBOL_GPL(fg_dm_read_block);
830
831static int fg_dm_write_block(struct bq_fg_chip *bq, u8 classid,
832 u8 offset, u8 *data)
833{
834 int ret;
835 u8 cksum;
836 u8 buf[64];
837 u8 blk_offset = offset >> 5;
838
839 pr_info("subclass:%d, offset:%d\n", classid, offset);
840
841 ret = fg_write_byte(bq, DM_ACCESS_BLOCK_DATA_CTRL, 0);
842 if (ret < 0)
843 return ret;
844 msleep(5);
845 ret = fg_write_byte(bq, DM_ACCESS_BLOCK_DATA_CLASS, classid);
846 if (ret < 0)
847 return ret;
848 msleep(5);
849 ret = fg_write_byte(bq, DM_ACCESS_DATA_BLOCK, blk_offset);
850 if (ret < 0)
851 return ret;
852 ret = fg_write_block(bq, DM_ACCESS_BLOCK_DATA, data, 32);
853 msleep(5);
854
855 fg_print_buf(__func__, data, 32);
856
857 cksum = checksum(data, 32);
858 ret = fg_write_byte(bq, DM_ACCESS_BLOCK_DATA_CHKSUM, cksum);
859 if (ret < 0)
860 return ret;
861 msleep(5);
862
863 ret = fg_write_byte(bq, DM_ACCESS_DATA_BLOCK, blk_offset);
864 if (ret < 0)
865 return ret;
866 msleep(5);
867 ret = fg_read_block(bq, DM_ACCESS_BLOCK_DATA, buf, 32);
868 if (ret < 0)
869 return ret;
870 if (memcpy(data, buf, 32)) {
871 pr_err("Error updating subclass %d offset %d\n",
872 classid, offset);
873 return 1;
874 }
875 return 0;
876}
877EXPORT_SYMBOL_GPL(fg_dm_write_block);
878
879static int fg_read_fw_version(struct bq_fg_chip *bq)
880{
881
882 int ret;
883 u16 version;
884
885 ret = fg_write_word(bq, bq->regs[BQ_FG_REG_CTRL], 0x0002);
886
887 if (ret < 0) {
888 pr_err("Failed to send firmware version subcommand:%d\n", ret);
889 return ret;
890 }
891
892 mdelay(2);
893
894 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_CTRL], &version);
895 if (ret < 0) {
896 pr_err("Failed to read firmware version:%d\n", ret);
897 return ret;
898 }
899
900 return version;
901}
902
903
904static int fg_read_status(struct bq_fg_chip *bq)
905{
906 int ret;
907 u16 flags;
908
909 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_FLAGS], &flags);
910 if (ret < 0) {
911 return ret;
912 }
913
914 mutex_lock(&bq->data_lock);
915 bq->batt_present = !!(flags & FG_FLAGS_BAT_DET);
916 bq->batt_ot = !!(flags & FG_FLAGS_OT);
917 bq->batt_ut = !!(flags & FG_FLAGS_UT);
918 bq->batt_fc = !!(flags & FG_FLAGS_FC);
919 bq->batt_soc1 = !!(flags & FG_FLAGS_SOC1);
920 bq->batt_socf = !!(flags & FG_FLAGS_SOCF);
921 bq->batt_dsg = !!(flags & FG_FLAGS_DSG);
922 bq->allow_chg = !!(flags & FG_FLAGS_CHG);
923 mutex_unlock(&bq->data_lock);
924
925 return 0;
926}
927
928
929static int fg_read_rsoc(struct bq_fg_chip *bq)
930{
931 int ret;
932 u16 soc = 0;
933
934 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_SOC], &soc);
935 if (ret < 0) {
936 pr_err("could not read RSOC, ret = %d\n", ret);
937 return ret;
938 }
939
940 return soc;
941
942}
943
944static int fg_read_temperature(struct bq_fg_chip *bq)
945{
946 int ret;
947 u16 temp = 0;
948
949 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_TEMP], &temp);
950 if (ret < 0) {
951 pr_err("could not read temperature, ret = %d\n", ret);
952 return ret;
953 }
954
955 return temp;
956
957}
958
959static int fg_read_volt(struct bq_fg_chip *bq)
960{
961 int ret;
962 u16 volt = 0;
963
964 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_VOLT], &volt);
965 if (ret < 0) {
966 pr_err("could not read voltage, ret = %d\n", ret);
967 return ret;
968 }
969
970 return volt;
971
972}
973
974static int fg_read_current(struct bq_fg_chip *bq, int *curr)
975{
976 int ret;
977 u16 avg_curr = 0;
978
979 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_AI], &avg_curr);
980 if (ret < 0) {
981 pr_err("could not read current, ret = %d\n", ret);
982 return ret;
983 }
984 *curr = (int)((s16)avg_curr);
985
986 return ret;
987}
988
989static int fg_read_fcc(struct bq_fg_chip *bq)
990{
991 int ret;
992 u16 fcc;
993
994 if (bq->regs[BQ_FG_REG_FCC] == INVALID_REG_ADDR) {
995 pr_err("FCC command not supported!\n");
996 return 0;
997 }
998
999 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_FCC], &fcc);
1000
1001 if (ret < 0) {
1002 pr_err("could not read FCC, ret=%d\n", ret);
1003 }
1004
1005 return fcc;
1006}
1007
1008static int fg_read_dc(struct bq_fg_chip *bq)
1009{
1010
1011 int ret;
1012 u16 dc;
1013
1014 if (bq->regs[BQ_FG_REG_DC] == INVALID_REG_ADDR) {
1015 pr_err("DesignCapacity command not supported!\n");
1016 return 0;
1017 }
1018
1019 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_DC], &dc);
1020
1021 if (ret < 0) {
1022 pr_err("could not read DC, ret=%d\n", ret);
1023 return ret;
1024 }
1025
1026 return dc;
1027}
1028
1029
1030static int fg_read_rm(struct bq_fg_chip *bq)
1031{
1032 int ret;
1033 u16 rm;
1034
1035 if (bq->regs[BQ_FG_REG_RM] == INVALID_REG_ADDR) {
1036 pr_err("RemainingCapacity command not supported!\n");
1037 return 0;
1038 }
1039
1040 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_RM], &rm);
1041
1042 if (ret < 0) {
1043 pr_err("could not read DC, ret=%d\n", ret);
1044 return ret;
1045 }
1046
1047 return rm;
1048
1049}
1050
1051static int fg_read_cyclecount(struct bq_fg_chip *bq)
1052{
1053 int ret;
1054 u16 cc;
1055
1056 if (bq->regs[BQ_FG_REG_CC] == INVALID_REG_ADDR) {
1057 pr_err("Cycle Count not supported!\n");
1058 return -1;
1059 }
1060
1061 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_CC], &cc);
1062
1063 if (ret < 0) {
1064 pr_err("could not read Cycle Count, ret=%d\n", ret);
1065 return ret;
1066 }
1067
1068 return cc;
1069}
1070
1071static int fg_read_tte(struct bq_fg_chip *bq)
1072{
1073 int ret;
1074 u16 tte;
1075
1076 if (bq->regs[BQ_FG_REG_TTE] == INVALID_REG_ADDR) {
1077 pr_err("Time To Empty not supported!\n");
1078 return -1;
1079 }
1080
1081 ret = fg_read_word(bq, bq->regs[BQ_FG_REG_TTE], &tte);
1082
1083 if (ret < 0) {
1084 pr_err("could not read Time To Empty, ret=%d\n", ret);
1085 return ret;
1086 }
1087
1088 if (ret == 0xFFFF)
1089 return -ENODATA;
1090
1091 return tte;
1092}
1093
1094static int fg_get_batt_status(struct bq_fg_chip *bq)
1095{
1096
1097 fg_read_status(bq);
1098
1099 if (!bq->batt_present)
1100 return POWER_SUPPLY_STATUS_UNKNOWN;
1101 else if (bq->batt_fc)
1102 return POWER_SUPPLY_STATUS_FULL;
1103 else if (bq->batt_dsg)
1104 return POWER_SUPPLY_STATUS_DISCHARGING;
1105 else if (bq->batt_curr > 0)
1106 return POWER_SUPPLY_STATUS_CHARGING;
1107 else
1108 return POWER_SUPPLY_STATUS_NOT_CHARGING;
1109
1110}
1111
1112
1113static int fg_get_batt_capacity_level(struct bq_fg_chip *bq)
1114{
1115 if (!bq->batt_present)
1116 return POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
1117 else if (bq->batt_fc)
1118 return POWER_SUPPLY_CAPACITY_LEVEL_FULL;
1119 else if (bq->batt_soc1)
1120 return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
1121 else if (bq->batt_socf)
1122 return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
1123 else
1124 return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
1125
1126}
1127
1128
1129static int fg_get_batt_health(struct bq_fg_chip *bq)
1130{
1131 if (!bq->batt_present)
1132 return POWER_SUPPLY_HEALTH_UNKNOWN;
1133 else if (bq->batt_ot)
1134 return POWER_SUPPLY_HEALTH_OVERHEAT;
1135 else if (bq->batt_ut)
1136 return POWER_SUPPLY_HEALTH_COLD;
1137 else
1138 return POWER_SUPPLY_HEALTH_GOOD;
1139
1140}
1141
1142static enum power_supply_property fg_props[] = {
1143 POWER_SUPPLY_PROP_STATUS,
1144 POWER_SUPPLY_PROP_PRESENT,
1145 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1146 POWER_SUPPLY_PROP_CURRENT_NOW,
1147 POWER_SUPPLY_PROP_CAPACITY,
1148 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
1149 POWER_SUPPLY_PROP_TEMP,
1150// POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
1151 POWER_SUPPLY_PROP_CHARGE_FULL,
1152// POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
1153// POWER_SUPPLY_PROP_CYCLE_COUNT,
1154 POWER_SUPPLY_PROP_HEALTH,
1155 POWER_SUPPLY_PROP_TECHNOLOGY,
1156 POWER_SUPPLY_PROP_UPDATE_NOW,
1157};
1158
1159static int fg_get_property(struct power_supply *psy, enum power_supply_property psp,
1160 union power_supply_propval *val)
1161{
1162 struct bq_fg_chip *bq = power_supply_get_drvdata(psy);
1163 int ret;
1164
1165 mutex_lock(&bq->update_lock);
1166 switch (psp) {
1167 case POWER_SUPPLY_PROP_STATUS:
1168 val->intval = fg_get_batt_status(bq);
1169 break;
1170 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1171 ret = fg_read_volt(bq);
1172 mutex_lock(&bq->data_lock);
1173 if (ret >= 0)
1174 bq->batt_volt = ret;
1175 val->intval = bq->batt_volt * 1000;
1176 mutex_unlock(&bq->data_lock);
1177
1178 break;
1179 case POWER_SUPPLY_PROP_PRESENT:
1180 val->intval = bq->batt_present;
1181 break;
1182 case POWER_SUPPLY_PROP_CURRENT_NOW:
1183 mutex_lock(&bq->data_lock);
1184 fg_read_current(bq, &bq->batt_curr);
1185 val->intval = -bq->batt_curr * 1000;
1186 pr_info("bq27426 current=%d\n", val->intval);
1187 mutex_unlock(&bq->data_lock);
1188 break;
1189
1190 case POWER_SUPPLY_PROP_CAPACITY:
1191 if (bq->fake_soc >= 0) {
1192 val->intval = bq->fake_soc;
1193 break;
1194 }
1195 ret = fg_read_rsoc(bq);
1196 mutex_lock(&bq->data_lock);
1197 if (ret >= 0)
1198 bq->batt_soc = ret;
1199 val->intval = bq->batt_soc;
1200 mutex_unlock(&bq->data_lock);
1201 break;
1202
1203 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
1204 val->intval = fg_get_batt_capacity_level(bq);
1205 break;
1206
1207 case POWER_SUPPLY_PROP_TEMP:
1208 if (bq->fake_temp != -EINVAL){
1209 val->intval = bq->fake_temp;
1210 break;
1211 }
1212 ret = fg_read_temperature(bq);
1213 mutex_lock(&bq->data_lock);
1214 if (ret > 0)
1215 bq->batt_temp = ret;
1216 val->intval = bq->batt_temp - 2730;
1217 mutex_unlock(&bq->data_lock);
1218 break;
1219
1220 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
1221 ret = fg_read_tte(bq);
1222 mutex_lock(&bq->data_lock);
1223 if (ret >=0)
1224 bq->batt_tte = ret;
1225
1226 val->intval = bq->batt_tte;
1227 mutex_unlock(&bq->data_lock);
1228 break;
1229
1230 case POWER_SUPPLY_PROP_CHARGE_FULL:
1231 ret = fg_read_fcc(bq);
1232 mutex_lock(&bq->data_lock);
1233 if (ret > 0)
1234 bq->batt_fcc = ret;
1235 val->intval = bq->batt_fcc * 1000;
1236 mutex_unlock(&bq->data_lock);
1237 break;
1238
1239 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
1240 ret = fg_read_dc(bq);
1241 mutex_lock(&bq->data_lock);
1242 if (ret > 0)
1243 bq->batt_dc = ret;
1244 val->intval = bq->batt_dc * 1000;
1245 mutex_unlock(&bq->data_lock);
1246 break;
1247
1248 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1249 ret = fg_read_cyclecount(bq);
1250 mutex_lock(&bq->data_lock);
1251 if (ret >= 0)
1252 bq->batt_cyclecnt = ret;
1253 val->intval = bq->batt_cyclecnt;
1254 mutex_unlock(&bq->data_lock);
1255 break;
1256
1257 case POWER_SUPPLY_PROP_HEALTH:
1258 val->intval = fg_get_batt_health(bq);
1259 break;
1260
1261 case POWER_SUPPLY_PROP_TECHNOLOGY:
1262 val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
1263 break;
1264
1265 case POWER_SUPPLY_PROP_UPDATE_NOW:
1266 val->intval = 0;
1267 break;
1268
1269 default:
1270 mutex_unlock(&bq->update_lock);
1271 return -EINVAL;
1272 }
1273 mutex_unlock(&bq->update_lock);
1274 return 0;
1275}
1276static void fg_dump_registers(struct bq_fg_chip *bq);
1277
1278static int fg_set_property(struct power_supply *psy,
1279 enum power_supply_property prop,
1280 const union power_supply_propval *val)
1281{
1282 struct bq_fg_chip *bq = power_supply_get_drvdata(psy);
1283
1284 switch (prop) {
1285 case POWER_SUPPLY_PROP_TEMP:
1286 bq->fake_temp = val->intval;
1287 break;
1288 case POWER_SUPPLY_PROP_CAPACITY:
1289 bq->fake_soc = val->intval;
1290 power_supply_changed(bq->fg_psy);
1291 break;
1292 case POWER_SUPPLY_PROP_UPDATE_NOW:
1293 fg_dump_registers(bq);
1294 break;
1295 default:
1296 return -EINVAL;
1297 }
1298
1299 return 0;
1300}
1301
1302
1303static int fg_prop_is_writeable(struct power_supply *psy,
1304 enum power_supply_property prop)
1305{
1306 int ret;
1307
1308 switch (prop) {
1309 case POWER_SUPPLY_PROP_TEMP:
1310 case POWER_SUPPLY_PROP_CAPACITY:
1311 case POWER_SUPPLY_PROP_UPDATE_NOW:
1312 ret = 1;
1313 break;
1314 default:
1315 ret = 0;
1316 break;
1317 }
1318 return ret;
1319}
1320
1321static int fg_psy_register(struct bq_fg_chip *bq)
1322{
1323 struct power_supply_config fg_psy_cfg = {};
1324
1325 bq->fg_psy_d.name = "bms";
1326 bq->fg_psy_d.type = POWER_SUPPLY_TYPE_BMS;
1327 bq->fg_psy_d.properties = fg_props;
1328 bq->fg_psy_d.num_properties = ARRAY_SIZE(fg_props);
1329 bq->fg_psy_d.get_property = fg_get_property;
1330 bq->fg_psy_d.set_property = fg_set_property;
1331 bq->fg_psy_d.property_is_writeable = fg_prop_is_writeable;
1332
1333 fg_psy_cfg.drv_data = bq;
1334 fg_psy_cfg.num_supplicants = 0;
1335 bq->fg_psy = devm_power_supply_register(bq->dev,
1336 &bq->fg_psy_d,
1337 &fg_psy_cfg);
1338 if (IS_ERR(bq->fg_psy)) {
1339 pr_err("Failed to register fg_psy");
1340 return PTR_ERR(bq->fg_psy);
1341 }
1342
1343 return 0;
1344}
1345
1346
1347static void fg_psy_unregister(struct bq_fg_chip *bq)
1348{
1349
1350 power_supply_unregister(bq->fg_psy);
1351}
1352
1353
1354static int fg_check_update_necessary(struct bq_fg_chip *bq)
1355{
1356 int ret;
1357 u8 dm_ver = 0xFF;
1358
1359 ret = fg_check_itpor(bq);
1360 if (!ret && bq->itpor)
1361 return UPDATE_REASON_FG_RESET;
1362
1363 ret = fg_read_dm_version(bq, &dm_ver);
1364 if (!ret && dm_ver < bqfs_image[bq->batt_id].version)
1365 return UPDATE_REASON_NEW_VERSION;
1366 else
1367 return 0;
1368}
1369
1370static bool fg_update_bqfs_execute_cmd(struct bq_fg_chip *bq,
1371 const bqfs_cmd_t *cmd)
1372{
1373 int ret;
1374 int i;
1375 u8 tmp_buf[CMD_MAX_DATA_SIZE];
1376
1377 switch (cmd->cmd_type) {
1378 case CMD_R:
1379 ret = fg_read_block(bq, cmd->reg, (u8 *)&cmd->data.bytes, cmd->data_len);
1380 if (ret < 0)
1381 return false;
1382 else
1383 return true;
1384 break;
1385 case CMD_W:
1386 ret = fg_write_block(bq, cmd->reg, (u8 *)&cmd->data.bytes, cmd->data_len);
1387 if (ret < 0)
1388 return false;
1389 else
1390 return true;
1391 break;
1392 case CMD_C:
1393 if (fg_read_block(bq, cmd->reg, tmp_buf, cmd->data_len) < 0)
1394 return false;
1395 if (memcmp(tmp_buf, cmd->data.bytes, cmd->data_len)) {
1396 pr_info("CMD_C failed at line %d\n", cmd->line_num);
1397 for(i = 0; i < cmd->data_len; i++) {
1398 pr_err("Read: %02X, Cmp:%02X", tmp_buf[i], cmd->data.bytes[i]);
1399 }
1400 return false;
1401 }
1402
1403 return true;
1404 break;
1405 case CMD_X:
1406 mdelay(cmd->data.delay);
1407 return true;
1408 break;
1409 default:
1410 pr_err("Unsupported command at line %d\n", cmd->line_num);
1411 return false;
1412 }
1413
1414}
1415EXPORT_SYMBOL_GPL(fg_update_bqfs_execute_cmd);
1416
1417static void fg_update_bqfs(struct bq_fg_chip *bq)
1418{
1419 int i;
1420 const bqfs_cmd_t *image;
1421 int reason = 0;
1422
1423
1424 if (bq->force_update == ~BQFS_UPDATE_KEY)
1425 reason = UPDATE_REASON_FORCED;
1426 else
1427 reason = fg_check_update_necessary(bq);
1428
1429 if (!reason) {
1430 pr_info("Fuel Gauge parameter no need update, ignored\n");
1431 return;
1432 }
1433
1434 if (bq->batt_id >= ARRAY_SIZE(bqfs_image) ||
1435 bq->batt_id < 0) {
1436 pr_err("batt_id is out of range");
1437 return;
1438 }
1439 /* TODO:if unseal, enter cfg update mode cmd sequence are in gmfs file,
1440 no need to do explicitly */
1441 fg_dm_pre_access(bq);
1442
1443 pr_err("Fuel Gauge parameter update, reason:%s, version:%d, batt_id=%d Start...\n",
1444 update_reason_str[reason - 1], bqfs_image[bq->batt_id].version, bq->batt_id);
1445
1446 mutex_lock(&bq->update_lock);
1447 image = bqfs_image[bq->batt_id].bqfs_image;
1448 for (i = 0; i < bqfs_image[bq->batt_id].array_size; i++) {
1449 if (!fg_update_bqfs_execute_cmd(bq, &image[i])) {
1450 mutex_unlock(&bq->update_lock);
1451 pr_err("Failed at command: %d\n", i);
1452 fg_dm_post_access(bq);
1453 return;
1454 }
1455 mdelay(5);
1456 }
1457 mutex_unlock(&bq->update_lock);
1458
1459 pr_err("Done!\n");
1460
1461 /* TODO:exit cfg update mode and seal device if these are not handled in gmfs file */
1462 fg_dm_post_access(bq);
1463 return;
1464
1465}
1466
1467static const u8 fg_dump_regs[] = {
1468 0x00, 0x02, 0x04, 0x06,
1469 0x08, 0x0A, 0x0C, 0x0E,
1470 0x10, 0x16, 0x18, 0x1A,
1471 0x1C, 0x1E, 0x20, 0x28,
1472 0x2A, 0x2C, 0x2E, 0x30,
1473 0x66, 0x68, 0x6C, 0x6E,
1474 0x70,
1475};
1476
1477static int show_registers(struct seq_file *m, void *data)
1478{
1479 struct bq_fg_chip *bq = m->private;
1480 int i;
1481 int ret;
1482 u16 val = 0;
1483
1484 for (i = 0; i < ARRAY_SIZE(fg_dump_regs); i++) {
1485 msleep(5);
1486 ret = fg_read_word(bq, fg_dump_regs[i], &val);
1487 if (!ret)
1488 seq_printf(m, "Reg[%02X] = 0x%04X\n",
1489 fg_dump_regs[i], val);
1490 }
1491 return 0;
1492}
1493
1494
1495static int reg_debugfs_open(struct inode *inode, struct file *file)
1496{
1497 struct bq_fg_chip *bq = inode->i_private;
1498
1499 return single_open(file, show_registers, bq);
1500}
1501
1502static const struct file_operations reg_debugfs_ops = {
1503 .owner = THIS_MODULE,
1504 .open = reg_debugfs_open,
1505 .read = seq_read,
1506 .llseek = seq_lseek,
1507 .release = single_release,
1508};
1509
1510static void create_debugfs_entry(struct bq_fg_chip *bq)
1511{
1512 bq->debug_root = debugfs_create_dir("bq_fg", NULL);
1513 if (!bq->debug_root)
1514 pr_err("Failed to create debug dir\n");
1515
1516 if (bq->debug_root) {
1517
1518 debugfs_create_file("registers", S_IFREG | S_IRUGO,
1519 bq->debug_root, bq, &reg_debugfs_ops);
1520
1521 debugfs_create_x32("fake_soc",
1522 S_IFREG | S_IWUSR | S_IRUGO,
1523 bq->debug_root,
1524 &(bq->fake_soc));
1525
1526 debugfs_create_x32("fake_temp",
1527 S_IFREG | S_IWUSR | S_IRUGO,
1528 bq->debug_root,
1529 &(bq->fake_temp));
1530
1531 debugfs_create_x32("skip_reads",
1532 S_IFREG | S_IWUSR | S_IRUGO,
1533 bq->debug_root,
1534 &(bq->skip_reads));
1535 debugfs_create_x32("skip_writes",
1536 S_IFREG | S_IWUSR | S_IRUGO,
1537 bq->debug_root,
1538 &(bq->skip_writes));
1539 }
1540}
1541
1542static ssize_t fg_attr_show_qmax_ratable(struct device *dev,
1543 struct device_attribute *attr, char *buf)
1544{
1545 struct i2c_client *client = to_i2c_client(dev);
1546 struct bq_fg_chip *bq = i2c_get_clientdata(client);
1547
1548 int ret;
1549 u8 rd_buf[512];
1550 int len;
1551 int idx = 0;
1552 int i;
1553
1554 mutex_lock(&bq->update_lock);
1555 ret = fg_dm_pre_access(bq);
1556 if (ret) {
1557 mutex_unlock(&bq->update_lock);
1558 return 0;
1559 }
1560
1561 ret = fg_dm_read_block(bq, 82, 0, rd_buf); //Qmax, offset 0
1562 if (ret) {
1563 fg_dm_post_access(bq);
1564 mutex_unlock(&bq->update_lock);
1565 return 0;
1566 }
1567
1568 len = sprintf(&buf[idx], "Qmax Cell 0: %d\n", (rd_buf[0] << 8) | rd_buf[1]);
1569 idx += len;
1570 len = sprintf(&buf[idx], "Avg I Last Run: %d\n", (short)(rd_buf[25] << 8 | rd_buf[26]));
1571 idx += len;
1572 len = sprintf(&buf[idx], "Avg P Last Run:%d\n", (short)(rd_buf[27] << 8 | rd_buf[28]));
1573 idx += len;
1574 len = sprintf(&buf[idx], "Delta Voltage:%d\n", (rd_buf[29] << 8 | rd_buf[30]));
1575 idx += len;
1576
1577 ret = fg_dm_read_block(bq, 89, 0, rd_buf); //Ra Table
1578 if (ret) {
1579 fg_dm_post_access(bq);
1580 mutex_unlock(&bq->update_lock);
1581 return idx;
1582 }
1583
1584 len = sprintf(&buf[idx], "Ra Table:\n");
1585 idx += len;
1586
1587 for (i = 0; i < 15; i += 2) {
1588 len = sprintf(&buf[idx], "%d ", rd_buf[i] << 8 | rd_buf[i+1]);
1589 idx += len;
1590 }
1591
1592
1593 ret = fg_dm_read_block(bq, 109, 6, rd_buf); //V at Chg Term
1594 if (ret) {
1595 fg_dm_post_access(bq);
1596 mutex_unlock(&bq->update_lock);
1597 return idx;
1598 }
1599
1600 len = sprintf(&buf[idx], "V at Chg Term:%d\n", rd_buf[6] << 8 | rd_buf[7]);
1601 idx += len;
1602
1603 fg_dm_post_access(bq);
1604
1605 mutex_unlock(&bq->update_lock);
1606
1607 return idx;
1608}
1609
1610static ssize_t fg_attr_store_update(struct device *dev,
1611 struct device_attribute *attr, const char *buf, size_t count)
1612{
1613
1614 struct i2c_client *client = to_i2c_client(dev);
1615 struct bq_fg_chip *bq = i2c_get_clientdata(client);
1616 unsigned int key = 0;
1617
1618 sscanf(buf, "%x", &key);
1619 if (key == BQFS_UPDATE_KEY) {
1620 bq->force_update = ~key;
1621 schedule_work(&bq->update_work);
1622 }
1623 return count;
1624}
1625
1626static ssize_t fg_attr_show_dmcode(struct device *dev,
1627 struct device_attribute *attr, char *buf)
1628{
1629 struct i2c_client *client = to_i2c_client(dev);
1630 struct bq_fg_chip *bq = i2c_get_clientdata(client);
1631
1632 int ret;
1633 u8 ver;
1634
1635 ret = fg_read_dm_version(bq, &ver);
1636 if (!ret)
1637 return sprintf(buf, "0x%02X\n", ver);
1638 else
1639 return sprintf(buf, "Read DM code error");
1640}
1641
1642
1643
1644static DEVICE_ATTR(qmax_ratable, S_IRUGO, fg_attr_show_qmax_ratable, NULL);
1645static DEVICE_ATTR(update, S_IWUSR, NULL, fg_attr_store_update);
1646static DEVICE_ATTR(dmcode, S_IRUGO, fg_attr_show_dmcode, NULL);
1647
1648static struct attribute *fg_attributes[] = {
1649 &dev_attr_qmax_ratable.attr,
1650 &dev_attr_update.attr,
1651 &dev_attr_dmcode.attr,
1652 NULL,
1653};
1654
1655static const struct attribute_group fg_attr_group = {
1656 .attrs = fg_attributes,
1657};
1658
1659
1660
1661static int fg_enable_sleep(struct bq_fg_chip *bq, bool enable)
1662{
1663
1664 int ret;
1665 u8 rd_buf[64];
1666
1667 memset(rd_buf, 0, 64);
1668 mutex_lock(&bq->update_lock);
1669 ret = fg_dm_enter_cfg_mode(bq);
1670 if (ret) {
1671 mutex_unlock(&bq->update_lock);
1672 return ret;
1673 }
1674
1675 ret = fg_dm_read_block(bq, 64, 0, rd_buf); //OpConfig
1676 if (ret) {
1677 fg_dm_exit_cfg_mode(bq);
1678 mutex_unlock(&bq->update_lock);
1679 return ret;
1680 }
1681
1682 if (enable)
1683 rd_buf[1] |=0x20; // set SLEEP bit
1684 else
1685 rd_buf[1] &=~0x20; // clear SLEEP bit
1686
1687
1688 ret = fg_dm_write_block(bq, 64, 0, rd_buf);
1689
1690 fg_dm_exit_cfg_mode(bq);
1691
1692 mutex_unlock(&bq->update_lock);
1693
1694 return ret;
1695}
1696EXPORT_SYMBOL_GPL(fg_enable_sleep);
1697
1698static void fg_update_bqfs_workfunc(struct work_struct *work)
1699{
1700 struct bq_fg_chip *bq = container_of(work,
1701 struct bq_fg_chip, update_work);
1702
1703 fg_update_bqfs(bq);
1704}
1705
1706static void fg_dump_registers(struct bq_fg_chip *bq)
1707{
1708 int i;
1709 int ret;
1710 u16 val;
1711
1712 for (i = 0; i < ARRAY_SIZE(fg_dump_regs); i++) {
1713 msleep(5);
1714 ret = fg_read_word(bq, fg_dump_regs[i], &val);
1715 if (!ret)
1716 pr_err("Reg[%02X] = 0x%04X\n", fg_dump_regs[i], val);
1717 }
1718}
1719
1720static irqreturn_t fg_irq_thread(int irq, void *dev_id)
1721{
1722 struct bq_fg_chip *bq = dev_id;
1723 bool last_batt_present;
1724
1725 mutex_lock(&bq->irq_complete);
1726 bq->irq_waiting = true;
1727 if (!bq->resume_completed) {
1728 pr_info("IRQ triggered before device resume\n");
1729 if (!bq->irq_disabled) {
1730 disable_irq_nosync(irq);
1731 bq->irq_disabled = true;
1732 }
1733 mutex_unlock(&bq->irq_complete);
1734 return IRQ_HANDLED;
1735 }
1736 bq->irq_waiting = false;
1737
1738 last_batt_present = bq->batt_present;
1739
1740 mutex_lock(&bq->update_lock);
1741 fg_read_status(bq);
1742 mutex_unlock(&bq->update_lock);
1743
1744 fg_dump_registers(bq);
1745
1746 pr_info("itpor=%d, cfg_mode = %d, seal_state=%d, batt_present=%d",
1747 bq->itpor, bq->cfg_update_mode, bq->seal_state, bq->batt_present);
1748
1749 if (!last_batt_present && bq->batt_present ) {/* battery inserted */
1750 pr_info("Battery inserted\n");
1751 } else if (last_batt_present && !bq->batt_present) {/* battery removed */
1752 pr_info("Battery removed\n");
1753 bq->batt_soc = -ENODATA;
1754 bq->batt_fcc = -ENODATA;
1755 bq->batt_rm = -ENODATA;
1756 bq->batt_volt = -ENODATA;
1757 bq->batt_curr = -ENODATA;
1758 bq->batt_temp = -ENODATA;
1759 bq->batt_cyclecnt = -ENODATA;
1760 }
1761
1762 if (bq->batt_present) {
1763 mutex_lock(&bq->update_lock);
1764
1765 bq->batt_soc = fg_read_rsoc(bq);
1766 bq->batt_volt = fg_read_volt(bq);
1767 fg_read_current(bq, &bq->batt_curr);
1768 bq->batt_temp = fg_read_temperature(bq);
1769 bq->batt_rm = fg_read_rm(bq);
1770
1771 mutex_unlock(&bq->update_lock);
1772 pr_err("RSOC:%d, Volt:%d, Current:%d, Temperature:%d\n",
1773 bq->batt_soc, bq->batt_volt, bq->batt_curr, bq->batt_temp - 2730);
1774 }
1775
1776 power_supply_changed(bq->fg_psy);
1777 mutex_unlock(&bq->irq_complete);
1778
1779 return IRQ_HANDLED;
1780}
1781
1782
1783static void determine_initial_status(struct bq_fg_chip *bq)
1784{
1785 fg_irq_thread(bq->client->irq, bq);
1786}
1787
1788static int bq_parse_dt(struct bq_fg_chip *bq)
1789{
1790 return 0;
1791}
1792
1793static int bq_fg_probe(struct i2c_client *client,
1794 const struct i2c_device_id *id)
1795{
1796
1797 int ret;
1798 struct bq_fg_chip *bq;
1799 u8 *regs;
1800
1801 bq = devm_kzalloc(&client->dev, sizeof(*bq), GFP_KERNEL);
1802
1803 if (!bq) {
1804 pr_err("Could not allocate memory\n");
1805 return -ENOMEM;
1806 }
1807
1808 bq->dev = &client->dev;
1809 bq->client = client;
1810 bq->chip = id->driver_data;
1811
1812 bq->batt_soc = -ENODATA;
1813 bq->batt_fcc = -ENODATA;
1814 bq->batt_rm = -ENODATA;
1815 bq->batt_dc = -ENODATA;
1816 bq->batt_volt = -ENODATA;
1817 bq->batt_temp = -ENODATA;
1818 bq->batt_curr = -ENODATA;
1819 bq->batt_cyclecnt = -ENODATA;
1820
1821 bq->fake_soc = -EINVAL;
1822 bq->fake_temp = -EINVAL;
1823
1824 if (bq->chip == BQ27426) {
1825 regs = bq27426_regs;
1826 } else {
1827 pr_err("unexpected fuel gauge: %d\n", bq->chip);
1828 regs = bq27426_regs;
1829 }
1830
1831 memcpy(bq->regs, regs, NUM_REGS);
1832
1833 i2c_set_clientdata(client, bq);
1834
1835 mutex_init(&bq->i2c_rw_lock);
1836 mutex_init(&bq->data_lock);
1837 mutex_init(&bq->update_lock);
1838 mutex_init(&bq->irq_complete);
1839
1840 bq->resume_completed = true;
1841 bq->irq_waiting = false;
1842
1843 ret = bq_parse_dt(bq);
1844 if (ret < 0) {
1845 dev_err(&client->dev, "Unable to parse DT nodes\n");
1846 //goto destroy_mutex;
1847 }
1848 INIT_WORK(&bq->update_work, fg_update_bqfs_workfunc);
1849
1850
1851 fg_update_bqfs(bq);
1852
1853 if (client->irq) {
1854 ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
1855 fg_irq_thread,
1856 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
1857 "bq fuel gauge irq", bq);
1858 if (ret < 0) {
1859 pr_err("request irq for irq=%d failed, ret = %d\n", client->irq, ret);
1860 goto err_1;
1861 }
1862 enable_irq_wake(client->irq);
1863 }
1864
1865 device_init_wakeup(bq->dev, 1);
1866
1867 bq->fw_ver = fg_read_fw_version(bq);
1868
1869 fg_psy_register(bq);
1870
1871 create_debugfs_entry(bq);
1872 ret = sysfs_create_group(&bq->dev->kobj, &fg_attr_group);
1873 if (ret) {
1874 pr_err("Failed to register sysfs, err:%d\n", ret);
1875 }
1876
1877 determine_initial_status(bq);
1878
1879 pr_err("bq fuel gauge probe successfully, %s FW ver:%d\n",
1880 device2str[bq->chip], bq->fw_ver);
1881
1882 return 0;
1883
1884err_1:
1885 fg_psy_unregister(bq);
1886 return ret;
1887}
1888
1889
1890static inline bool is_device_suspended(struct bq_fg_chip *bq)
1891{
1892 return !bq->resume_completed;
1893}
1894
1895
1896static int bq_fg_suspend(struct device *dev)
1897{
1898 struct i2c_client *client = to_i2c_client(dev);
1899 struct bq_fg_chip *bq = i2c_get_clientdata(client);
1900
1901 mutex_lock(&bq->irq_complete);
1902 bq->resume_completed = false;
1903 mutex_unlock(&bq->irq_complete);
1904
1905 return 0;
1906}
1907
1908static int bq_fg_suspend_noirq(struct device *dev)
1909{
1910 struct i2c_client *client = to_i2c_client(dev);
1911 struct bq_fg_chip *bq = i2c_get_clientdata(client);
1912
1913 if (bq->irq_waiting) {
1914 pr_err_ratelimited("Aborting suspend, an interrupt was detected while suspending\n");
1915 return -EBUSY;
1916 }
1917 return 0;
1918
1919}
1920
1921
1922static int bq_fg_resume(struct device *dev)
1923{
1924 struct i2c_client *client = to_i2c_client(dev);
1925 struct bq_fg_chip *bq = i2c_get_clientdata(client);
1926
1927 mutex_lock(&bq->irq_complete);
1928 bq->resume_completed = true;
1929 if (bq->irq_waiting) {
1930 bq->irq_disabled = false;
1931 enable_irq(client->irq);
1932 mutex_unlock(&bq->irq_complete);
1933 fg_irq_thread(client->irq, bq);
1934 } else {
1935 mutex_unlock(&bq->irq_complete);
1936 }
1937
1938 power_supply_changed(bq->fg_psy);
1939
1940 return 0;
1941
1942
1943}
1944
1945static int bq_fg_remove(struct i2c_client *client)
1946{
1947 struct bq_fg_chip *bq = i2c_get_clientdata(client);
1948
1949 fg_psy_unregister(bq);
1950
1951 mutex_destroy(&bq->data_lock);
1952 mutex_destroy(&bq->i2c_rw_lock);
1953 mutex_destroy(&bq->update_lock);
1954 mutex_destroy(&bq->irq_complete);
1955
1956 debugfs_remove_recursive(bq->debug_root);
1957 sysfs_remove_group(&bq->dev->kobj, &fg_attr_group);
1958
1959 return 0;
1960
1961}
1962
1963static void bq_fg_shutdown(struct i2c_client *client)
1964{
1965 pr_info("bq fuel gauge driver shutdown!\n");
1966}
1967
1968static struct of_device_id bq_fg_match_table[] = {
1969 {.compatible = "ti,bq27426",},
1970 {},
1971};
1972MODULE_DEVICE_TABLE(of,bq_fg_match_table);
1973
1974static const struct i2c_device_id bq_fg_id[] = {
1975 { "bq27426", BQ27426 },
1976 {},
1977};
1978MODULE_DEVICE_TABLE(i2c, bq_fg_id);
1979
1980static const struct dev_pm_ops bq_fg_pm_ops = {
1981 .resume = bq_fg_resume,
1982 .suspend_noirq = bq_fg_suspend_noirq,
1983 .suspend = bq_fg_suspend,
1984};
1985
1986static struct i2c_driver bq_fg_driver = {
1987 .driver = {
1988 .name = "bq_fg",
1989 .owner = THIS_MODULE,
1990 .of_match_table = bq_fg_match_table,
1991 .pm = &bq_fg_pm_ops,
1992 },
1993 .id_table = bq_fg_id,
1994
1995 .probe = bq_fg_probe,
1996 .remove = bq_fg_remove,
1997 .shutdown = bq_fg_shutdown,
1998
1999};
2000
2001module_i2c_driver(bq_fg_driver);
2002
2003MODULE_DESCRIPTION("TI BQ2742x Gauge Driver");
2004MODULE_LICENSE("GPL v2");
2005MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/power/bq27426/bq27426_gmfs_coslight.h b/drivers/power/bq27426/bq27426_gmfs_coslight.h
new file mode 100644
index 000000000000..4c55bb2dff16
--- /dev/null
+++ b/drivers/power/bq27426/bq27426_gmfs_coslight.h
@@ -0,0 +1,945 @@
1/*****************************************************************************
2* Copyright 2010 Texas Instruments Corporation, All Rights Reserved.
3* TI makes NO WARRANTY as to software products, which are supplied "AS-IS"
4*****************************************************************************/
5
6/*****************************************************************************
7* This code is automatically generated from bqfs/dffs file. *
8* DO NOT MODIFY THIS FILE DIRECTLY *
9*****************************************************************************/
10
11
12#ifndef __BQFS_FILE__
13#define __BQFS_FILE__
14
15#include "bqfs_cmd_type.h"
16
17static const bqfs_cmd_t bqfs_coslight[] = {
18 {
19 .cmd_type = CMD_W,
20 .addr = 0xAA,
21 .reg = 0x00,
22 .data = {.bytes = {0x01, 0x00}},
23 .data_len = 2,
24 },
25 {
26 .cmd_type = CMD_C,
27 .addr = 0xAA,
28 .reg = 0x00,
29 .data = {.bytes = {0x26, 0x04}},
30 .data_len = 2,
31 },
32 {
33 .cmd_type = CMD_W,
34 .addr = 0xAA,
35 .reg = 0x00,
36 .data = {.bytes = {0x02, 0x00}},
37 .data_len = 2,
38 },
39 {
40 .cmd_type = CMD_C,
41 .addr = 0xAA,
42 .reg = 0x00,
43 .data = {.bytes = {0x02, 0x02}},
44 .data_len = 2,
45 },
46 {
47 .cmd_type = CMD_W,
48 .addr = 0xAA,
49 .reg = 0x3E,
50 .data = {.bytes = {0x02, 0x00}},
51 .data_len = 2,
52 },
53 {
54 .cmd_type = CMD_W,
55 .addr = 0xAA,
56 .reg = 0x40,
57 .data = {.bytes = {0x02, 0x26, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
58 .data_len = 32,
59 },
60 {
61 .cmd_type = CMD_W,
62 .addr = 0xAA,
63 .reg = 0x60,
64 .data = {.bytes = {0xA5}},
65 .data_len = 1,
66 },
67 {
68 .cmd_type = CMD_X,
69 .data = {.delay = 10},
70 },
71 {
72 .cmd_type = CMD_W,
73 .addr = 0xAA,
74 .reg = 0x3E,
75 .data = {.bytes = {0x02, 0x00}},
76 .data_len = 2,
77 },
78 {
79 .cmd_type = CMD_C,
80 .addr = 0xAA,
81 .reg = 0x60,
82 .data = {.bytes = {0xA5}},
83 .data_len = 1,
84 },
85 {
86 .cmd_type = CMD_W,
87 .addr = 0xAA,
88 .reg = 0x3E,
89 .data = {.bytes = {0x24, 0x00}},
90 .data_len = 2,
91 },
92 {
93 .cmd_type = CMD_W,
94 .addr = 0xAA,
95 .reg = 0x40,
96 .data = {.bytes = {0x00, 0x19, 0x28, 0x63, 0x5F, 0xFF, 0x62, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
97 .data_len = 32,
98 },
99 {
100 .cmd_type = CMD_W,
101 .addr = 0xAA,
102 .reg = 0x60,
103 .data = {.bytes = {0x69}},
104 .data_len = 1,
105 },
106 {
107 .cmd_type = CMD_X,
108 .data = {.delay = 10},
109 },
110 {
111 .cmd_type = CMD_W,
112 .addr = 0xAA,
113 .reg = 0x3E,
114 .data = {.bytes = {0x24, 0x00}},
115 .data_len = 2,
116 },
117 {
118 .cmd_type = CMD_C,
119 .addr = 0xAA,
120 .reg = 0x60,
121 .data = {.bytes = {0x69}},
122 .data_len = 1,
123 },
124 {
125 .cmd_type = CMD_W,
126 .addr = 0xAA,
127 .reg = 0x3E,
128 .data = {.bytes = {0x31, 0x00}},
129 .data_len = 2,
130 },
131 {
132 .cmd_type = CMD_W,
133 .addr = 0xAA,
134 .reg = 0x40,
135 .data = {.bytes = {0x0A, 0x0F, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
136 .data_len = 32,
137 },
138 {
139 .cmd_type = CMD_W,
140 .addr = 0xAA,
141 .reg = 0x60,
142 .data = {.bytes = {0xDF}},
143 .data_len = 1,
144 },
145 {
146 .cmd_type = CMD_X,
147 .data = {.delay = 10},
148 },
149 {
150 .cmd_type = CMD_W,
151 .addr = 0xAA,
152 .reg = 0x3E,
153 .data = {.bytes = {0x31, 0x00}},
154 .data_len = 2,
155 },
156 {
157 .cmd_type = CMD_C,
158 .addr = 0xAA,
159 .reg = 0x60,
160 .data = {.bytes = {0xDF}},
161 .data_len = 1,
162 },
163 {
164 .cmd_type = CMD_W,
165 .addr = 0xAA,
166 .reg = 0x3E,
167 .data = {.bytes = {0x40, 0x00}},
168 .data_len = 2,
169 },
170 {
171 .cmd_type = CMD_W,
172 .addr = 0xAA,
173 .reg = 0x40,
174 .data = {.bytes = {0x64, 0x79, 0x07, 0x9F, 0x23, 0x00, 0x00, 0x14, 0x04, 0x00, 0x09, 0x04, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
175 .data_len = 32,
176 },
177 {
178 .cmd_type = CMD_W,
179 .addr = 0xAA,
180 .reg = 0x60,
181 .data = {.bytes = {0x0E}},
182 .data_len = 1,
183 },
184 {
185 .cmd_type = CMD_X,
186 .data = {.delay = 10},
187 },
188 {
189 .cmd_type = CMD_W,
190 .addr = 0xAA,
191 .reg = 0x3E,
192 .data = {.bytes = {0x40, 0x00}},
193 .data_len = 2,
194 },
195 {
196 .cmd_type = CMD_C,
197 .addr = 0xAA,
198 .reg = 0x60,
199 .data = {.bytes = {0x0E}},
200 .data_len = 1,
201 },
202 {
203 .cmd_type = CMD_W,
204 .addr = 0xAA,
205 .reg = 0x3E,
206 .data = {.bytes = {0x44, 0x00}},
207 .data_len = 2,
208 },
209 {
210 .cmd_type = CMD_W,
211 .addr = 0xAA,
212 .reg = 0x40,
213 .data = {.bytes = {0x00, 0x32, 0x01, 0xC2, 0x30, 0x00, 0x03, 0x08, 0x98, 0x01, 0x00, 0x3C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
214 .data_len = 32,
215 },
216 {
217 .cmd_type = CMD_W,
218 .addr = 0xAA,
219 .reg = 0x60,
220 .data = {.bytes = {0xF9}},
221 .data_len = 1,
222 },
223 {
224 .cmd_type = CMD_X,
225 .data = {.delay = 10},
226 },
227 {
228 .cmd_type = CMD_W,
229 .addr = 0xAA,
230 .reg = 0x3E,
231 .data = {.bytes = {0x44, 0x00}},
232 .data_len = 2,
233 },
234 {
235 .cmd_type = CMD_C,
236 .addr = 0xAA,
237 .reg = 0x60,
238 .data = {.bytes = {0xF9}},
239 .data_len = 1,
240 },
241 {
242 .cmd_type = CMD_W,
243 .addr = 0xAA,
244 .reg = 0x3E,
245 .data = {.bytes = {0x50, 0x00}},
246 .data_len = 2,
247 },
248 {
249 .cmd_type = CMD_W,
250 .addr = 0xAA,
251 .reg = 0x40,
252 .data = {.bytes = {0x01, 0xF4, 0x00, 0x1E, 0xC8, 0x14, 0x08, 0x00, 0x3C, 0x0E, 0x10, 0x00, 0x0A, 0x46, 0x05, 0x14, 0x05, 0x0F, 0x03, 0x20, 0x7F, 0xFF, 0x00, 0xF0, 0x46, 0x50, 0x18, 0x01, 0x90, 0x00, 0x64, 0x19}},
253 .data_len = 32,
254 },
255 {
256 .cmd_type = CMD_W,
257 .addr = 0xAA,
258 .reg = 0x60,
259 .data = {.bytes = {0xE4}},
260 .data_len = 1,
261 },
262 {
263 .cmd_type = CMD_X,
264 .data = {.delay = 10},
265 },
266 {
267 .cmd_type = CMD_W,
268 .addr = 0xAA,
269 .reg = 0x3E,
270 .data = {.bytes = {0x50, 0x00}},
271 .data_len = 2,
272 },
273 {
274 .cmd_type = CMD_C,
275 .addr = 0xAA,
276 .reg = 0x60,
277 .data = {.bytes = {0xE4}},
278 .data_len = 1,
279 },
280 {
281 .cmd_type = CMD_W,
282 .addr = 0xAA,
283 .reg = 0x3E,
284 .data = {.bytes = {0x50, 0x01}},
285 .data_len = 2,
286 },
287 {
288 .cmd_type = CMD_W,
289 .addr = 0xAA,
290 .reg = 0x40,
291 .data = {.bytes = {0xDC, 0x5C, 0x60, 0x00, 0x7D, 0x00, 0x04, 0x03, 0x19, 0x25, 0x0F, 0x14, 0x0A, 0x78, 0x60, 0x28, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x43, 0x80, 0x04, 0x01, 0x14, 0x00, 0x08, 0x0B, 0xB8, 0x01}},
292 .data_len = 32,
293 },
294 {
295 .cmd_type = CMD_W,
296 .addr = 0xAA,
297 .reg = 0x60,
298 .data = {.bytes = {0xDB}},
299 .data_len = 1,
300 },
301 {
302 .cmd_type = CMD_X,
303 .data = {.delay = 10},
304 },
305 {
306 .cmd_type = CMD_W,
307 .addr = 0xAA,
308 .reg = 0x3E,
309 .data = {.bytes = {0x50, 0x01}},
310 .data_len = 2,
311 },
312 {
313 .cmd_type = CMD_C,
314 .addr = 0xAA,
315 .reg = 0x60,
316 .data = {.bytes = {0xDB}},
317 .data_len = 1,
318 },
319 {
320 .cmd_type = CMD_W,
321 .addr = 0xAA,
322 .reg = 0x3E,
323 .data = {.bytes = {0x50, 0x02}},
324 .data_len = 2,
325 },
326 {
327 .cmd_type = CMD_W,
328 .addr = 0xAA,
329 .reg = 0x40,
330 .data = {.bytes = {0x2C, 0x0A, 0x01, 0x0A, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x64, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x01, 0x03, 0x5A, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
331 .data_len = 32,
332 },
333 {
334 .cmd_type = CMD_W,
335 .addr = 0xAA,
336 .reg = 0x60,
337 .data = {.bytes = {0x59}},
338 .data_len = 1,
339 },
340 {
341 .cmd_type = CMD_X,
342 .data = {.delay = 10},
343 },
344 {
345 .cmd_type = CMD_W,
346 .addr = 0xAA,
347 .reg = 0x3E,
348 .data = {.bytes = {0x50, 0x02}},
349 .data_len = 2,
350 },
351 {
352 .cmd_type = CMD_C,
353 .addr = 0xAA,
354 .reg = 0x60,
355 .data = {.bytes = {0x59}},
356 .data_len = 1,
357 },
358 {
359 .cmd_type = CMD_W,
360 .addr = 0xAA,
361 .reg = 0x3E,
362 .data = {.bytes = {0x51, 0x00}},
363 .data_len = 2,
364 },
365 {
366 .cmd_type = CMD_W,
367 .addr = 0xAA,
368 .reg = 0x40,
369 .data = {.bytes = {0x01, 0x77, 0x01, 0x2C, 0x02, 0x58, 0x00, 0x3C, 0x3C, 0x01, 0xB3, 0xB3, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
370 .data_len = 32,
371 },
372 {
373 .cmd_type = CMD_W,
374 .addr = 0xAA,
375 .reg = 0x60,
376 .data = {.bytes = {0x90}},
377 .data_len = 1,
378 },
379 {
380 .cmd_type = CMD_X,
381 .data = {.delay = 10},
382 },
383 {
384 .cmd_type = CMD_W,
385 .addr = 0xAA,
386 .reg = 0x3E,
387 .data = {.bytes = {0x51, 0x00}},
388 .data_len = 2,
389 },
390 {
391 .cmd_type = CMD_C,
392 .addr = 0xAA,
393 .reg = 0x60,
394 .data = {.bytes = {0x90}},
395 .data_len = 1,
396 },
397 {
398 .cmd_type = CMD_W,
399 .addr = 0xAA,
400 .reg = 0x3E,
401 .data = {.bytes = {0x52, 0x00}},
402 .data_len = 2,
403 },
404 {
405 .cmd_type = CMD_W,
406 .addr = 0xAA,
407 .reg = 0x40,
408 .data = {.bytes = {0x40, 0x00, 0x02, 0x00, 0x32, 0x81, 0x0C, 0x08, 0x2E, 0x52, 0x0C, 0x1C, 0x00, 0xC8, 0x00, 0x32, 0x00, 0x14, 0x03, 0xE8, 0x01, 0x01, 0x00, 0x00, 0x0A, 0xFF, 0xCE, 0xFF, 0xCE, 0x00, 0x01, 0x00}},
409 .data_len = 32,
410 },
411 {
412 .cmd_type = CMD_W,
413 .addr = 0xAA,
414 .reg = 0x60,
415 .data = {.bytes = {0xAE}},
416 .data_len = 1,
417 },
418 {
419 .cmd_type = CMD_X,
420 .data = {.delay = 10},
421 },
422 {
423 .cmd_type = CMD_W,
424 .addr = 0xAA,
425 .reg = 0x3E,
426 .data = {.bytes = {0x52, 0x00}},
427 .data_len = 2,
428 },
429 {
430 .cmd_type = CMD_C,
431 .addr = 0xAA,
432 .reg = 0x60,
433 .data = {.bytes = {0xAE}},
434 .data_len = 1,
435 },
436 {
437 .cmd_type = CMD_W,
438 .addr = 0xAA,
439 .reg = 0x3E,
440 .data = {.bytes = {0x53, 0x00}},
441 .data_len = 2,
442 },
443 {
444 .cmd_type = CMD_W,
445 .addr = 0xAA,
446 .reg = 0x40,
447 .data = {.bytes = {0x15, 0x07, 0x11, 0x2C, 0xD3, 0xD7, 0xE0, 0xE0, 0xE3, 0xE3, 0xE6, 0xE5, 0xE5, 0xEA, 0xF4, 0xD3, 0xCA, 0xF3, 0xF3, 0xEB, 0xF0, 0xE2, 0xF0, 0xEE, 0xF2, 0xF2, 0xF7, 0xF9, 0xFA, 0xFA, 0xFC, 0xFE}},
448 .data_len = 32,
449 },
450 {
451 .cmd_type = CMD_W,
452 .addr = 0xAA,
453 .reg = 0x60,
454 .data = {.bytes = {0x08}},
455 .data_len = 1,
456 },
457 {
458 .cmd_type = CMD_X,
459 .data = {.delay = 10},
460 },
461 {
462 .cmd_type = CMD_W,
463 .addr = 0xAA,
464 .reg = 0x3E,
465 .data = {.bytes = {0x53, 0x00}},
466 .data_len = 2,
467 },
468 {
469 .cmd_type = CMD_C,
470 .addr = 0xAA,
471 .reg = 0x60,
472 .data = {.bytes = {0x08}},
473 .data_len = 1,
474 },
475 {
476 .cmd_type = CMD_W,
477 .addr = 0xAA,
478 .reg = 0x3E,
479 .data = {.bytes = {0x53, 0x01}},
480 .data_len = 2,
481 },
482 {
483 .cmd_type = CMD_W,
484 .addr = 0xAA,
485 .reg = 0x40,
486 .data = {.bytes = {0xF8, 0xF9, 0xF8, 0xF6, 0xEF, 0xF0, 0xF0, 0xFE, 0xFD, 0xE9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
487 .data_len = 32,
488 },
489 {
490 .cmd_type = CMD_W,
491 .addr = 0xAA,
492 .reg = 0x60,
493 .data = {.bytes = {0xED}},
494 .data_len = 1,
495 },
496 {
497 .cmd_type = CMD_X,
498 .data = {.delay = 10},
499 },
500 {
501 .cmd_type = CMD_W,
502 .addr = 0xAA,
503 .reg = 0x3E,
504 .data = {.bytes = {0x53, 0x01}},
505 .data_len = 2,
506 },
507 {
508 .cmd_type = CMD_C,
509 .addr = 0xAA,
510 .reg = 0x60,
511 .data = {.bytes = {0xED}},
512 .data_len = 1,
513 },
514 {
515 .cmd_type = CMD_W,
516 .addr = 0xAA,
517 .reg = 0x3E,
518 .data = {.bytes = {0x54, 0x00}},
519 .data_len = 2,
520 },
521 {
522 .cmd_type = CMD_W,
523 .addr = 0xAA,
524 .reg = 0x40,
525 .data = {.bytes = {0xFB, 0x1D, 0x05, 0x09, 0x06, 0x03, 0x02, 0xFF, 0x00, 0xFC, 0xFF, 0xFD, 0xFF, 0xFA, 0x0E, 0x19, 0x02, 0x01, 0x02, 0xFB, 0xF5, 0xF5, 0x02, 0x01, 0x05, 0xFE, 0xFB, 0xFD, 0xFE, 0xFC, 0xF7, 0xFB}},
526 .data_len = 32,
527 },
528 {
529 .cmd_type = CMD_W,
530 .addr = 0xAA,
531 .reg = 0x60,
532 .data = {.bytes = {0xE3}},
533 .data_len = 1,
534 },
535 {
536 .cmd_type = CMD_X,
537 .data = {.delay = 10},
538 },
539 {
540 .cmd_type = CMD_W,
541 .addr = 0xAA,
542 .reg = 0x3E,
543 .data = {.bytes = {0x54, 0x00}},
544 .data_len = 2,
545 },
546 {
547 .cmd_type = CMD_C,
548 .addr = 0xAA,
549 .reg = 0x60,
550 .data = {.bytes = {0xE3}},
551 .data_len = 1,
552 },
553 {
554 .cmd_type = CMD_W,
555 .addr = 0xAA,
556 .reg = 0x3E,
557 .data = {.bytes = {0x54, 0x01}},
558 .data_len = 2,
559 },
560 {
561 .cmd_type = CMD_W,
562 .addr = 0xAA,
563 .reg = 0x40,
564 .data = {.bytes = {0xFA, 0xFD, 0xFE, 0x03, 0xFA, 0x0B, 0xFE, 0x03, 0xB9, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
565 .data_len = 32,
566 },
567 {
568 .cmd_type = CMD_W,
569 .addr = 0xAA,
570 .reg = 0x60,
571 .data = {.bytes = {0xC7}},
572 .data_len = 1,
573 },
574 {
575 .cmd_type = CMD_X,
576 .data = {.delay = 10},
577 },
578 {
579 .cmd_type = CMD_W,
580 .addr = 0xAA,
581 .reg = 0x3E,
582 .data = {.bytes = {0x54, 0x01}},
583 .data_len = 2,
584 },
585 {
586 .cmd_type = CMD_C,
587 .addr = 0xAA,
588 .reg = 0x60,
589 .data = {.bytes = {0xC7}},
590 .data_len = 1,
591 },
592 {
593 .cmd_type = CMD_W,
594 .addr = 0xAA,
595 .reg = 0x3E,
596 .data = {.bytes = {0x55, 0x00}},
597 .data_len = 2,
598 },
599 {
600 .cmd_type = CMD_W,
601 .addr = 0xAA,
602 .reg = 0x40,
603 .data = {.bytes = {0xFF, 0x4B, 0x01, 0x05, 0x02, 0x06, 0x06, 0xFF, 0x03, 0xFA, 0x01, 0xFD, 0xFA, 0x01, 0x1A, 0xE5, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
604 .data_len = 32,
605 },
606 {
607 .cmd_type = CMD_W,
608 .addr = 0xAA,
609 .reg = 0x60,
610 .data = {.bytes = {0x33}},
611 .data_len = 1,
612 },
613 {
614 .cmd_type = CMD_X,
615 .data = {.delay = 10},
616 },
617 {
618 .cmd_type = CMD_W,
619 .addr = 0xAA,
620 .reg = 0x3E,
621 .data = {.bytes = {0x55, 0x00}},
622 .data_len = 2,
623 },
624 {
625 .cmd_type = CMD_C,
626 .addr = 0xAA,
627 .reg = 0x60,
628 .data = {.bytes = {0x33}},
629 .data_len = 1,
630 },
631 {
632 .cmd_type = CMD_W,
633 .addr = 0xAA,
634 .reg = 0x3E,
635 .data = {.bytes = {0x6C, 0x00}},
636 .data_len = 2,
637 },
638 {
639 .cmd_type = CMD_W,
640 .addr = 0xAA,
641 .reg = 0x40,
642 .data = {.bytes = {0xFE, 0xE0, 0x00, 0x00, 0x28, 0x08, 0x42, 0xDF, 0xFE, 0xE5, 0xFB, 0xFD, 0xF8, 0xED, 0x0F, 0x09, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
643 .data_len = 32,
644 },
645 {
646 .cmd_type = CMD_W,
647 .addr = 0xAA,
648 .reg = 0x60,
649 .data = {.bytes = {0xEE}},
650 .data_len = 1,
651 },
652 {
653 .cmd_type = CMD_X,
654 .data = {.delay = 10},
655 },
656 {
657 .cmd_type = CMD_W,
658 .addr = 0xAA,
659 .reg = 0x3E,
660 .data = {.bytes = {0x6C, 0x00}},
661 .data_len = 2,
662 },
663 {
664 .cmd_type = CMD_C,
665 .addr = 0xAA,
666 .reg = 0x60,
667 .data = {.bytes = {0xEE}},
668 .data_len = 1,
669 },
670 {
671 .cmd_type = CMD_W,
672 .addr = 0xAA,
673 .reg = 0x3E,
674 .data = {.bytes = {0x59, 0x00}},
675 .data_len = 2,
676 },
677 {
678 .cmd_type = CMD_W,
679 .addr = 0xAA,
680 .reg = 0x40,
681 .data = {.bytes = {0x00, 0x0D, 0x00, 0x09, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x23, 0x00, 0x15, 0x00, 0x18, 0x00, 0x17, 0x00, 0x17, 0x00, 0x18, 0x00, 0x18, 0x00, 0x16, 0x00, 0x24, 0x00, 0x25, 0x00, 0x5B, 0x00, 0x00}},
682 .data_len = 32,
683 },
684 {
685 .cmd_type = CMD_W,
686 .addr = 0xAA,
687 .reg = 0x60,
688 .data = {.bytes = {0x63}},
689 .data_len = 1,
690 },
691 {
692 .cmd_type = CMD_X,
693 .data = {.delay = 10},
694 },
695 {
696 .cmd_type = CMD_W,
697 .addr = 0xAA,
698 .reg = 0x3E,
699 .data = {.bytes = {0x59, 0x00}},
700 .data_len = 2,
701 },
702 {
703 .cmd_type = CMD_C,
704 .addr = 0xAA,
705 .reg = 0x60,
706 .data = {.bytes = {0x63}},
707 .data_len = 1,
708 },
709 {
710 .cmd_type = CMD_W,
711 .addr = 0xAA,
712 .reg = 0x3E,
713 .data = {.bytes = {0x6D, 0x00}},
714 .data_len = 2,
715 },
716 {
717 .cmd_type = CMD_W,
718 .addr = 0xAA,
719 .reg = 0x40,
720 .data = {.bytes = {0x0E, 0xBB, 0x0E, 0xE3, 0x0E, 0x9C, 0x11, 0x30, 0x10, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
721 .data_len = 32,
722 },
723 {
724 .cmd_type = CMD_W,
725 .addr = 0xAA,
726 .reg = 0x60,
727 .data = {.bytes = {0x4C}},
728 .data_len = 1,
729 },
730 {
731 .cmd_type = CMD_X,
732 .data = {.delay = 10},
733 },
734 {
735 .cmd_type = CMD_W,
736 .addr = 0xAA,
737 .reg = 0x3E,
738 .data = {.bytes = {0x6D, 0x00}},
739 .data_len = 2,
740 },
741 {
742 .cmd_type = CMD_C,
743 .addr = 0xAA,
744 .reg = 0x60,
745 .data = {.bytes = {0x4C}},
746 .data_len = 1,
747 },
748 {
749 .cmd_type = CMD_W,
750 .addr = 0xAA,
751 .reg = 0x3E,
752 .data = {.bytes = {0x68, 0x00}},
753 .data_len = 2,
754 },
755 {
756 .cmd_type = CMD_W,
757 .addr = 0xAA,
758 .reg = 0x40,
759 .data = {.bytes = {0x00, 0x00, 0x00, 0x00, 0xD4, 0x86, 0x4A, 0xC6, 0xB4, 0xC2, 0x6E, 0x2B, 0x03, 0x7C, 0x01, 0x48, 0xFD, 0xA3, 0xF6, 0x75, 0x12, 0x58, 0x2D, 0xB7, 0x00, 0x00, 0x00, 0x00, 0xCB, 0xD4, 0x1A, 0x05}},
760 .data_len = 32,
761 },
762 {
763 .cmd_type = CMD_W,
764 .addr = 0xAA,
765 .reg = 0x60,
766 .data = {.bytes = {0xA7}},
767 .data_len = 1,
768 },
769 {
770 .cmd_type = CMD_X,
771 .data = {.delay = 10},
772 },
773 {
774 .cmd_type = CMD_W,
775 .addr = 0xAA,
776 .reg = 0x3E,
777 .data = {.bytes = {0x68, 0x00}},
778 .data_len = 2,
779 },
780 {
781 .cmd_type = CMD_C,
782 .addr = 0xAA,
783 .reg = 0x60,
784 .data = {.bytes = {0xA7}},
785 .data_len = 1,
786 },
787 {
788 .cmd_type = CMD_W,
789 .addr = 0xAA,
790 .reg = 0x3E,
791 .data = {.bytes = {0x68, 0x01}},
792 .data_len = 2,
793 },
794 {
795 .cmd_type = CMD_W,
796 .addr = 0xAA,
797 .reg = 0x40,
798 .data = {.bytes = {0x1C, 0x98, 0x02, 0xD3, 0xFF, 0xB9, 0x30, 0xEF, 0x05, 0x11, 0x05, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x3C, 0x00, 0x50, 0x3C, 0x00, 0x64, 0x3C, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
799 .data_len = 32,
800 },
801 {
802 .cmd_type = CMD_W,
803 .addr = 0xAA,
804 .reg = 0x60,
805 .data = {.bytes = {0xEA}},
806 .data_len = 1,
807 },
808 {
809 .cmd_type = CMD_X,
810 .data = {.delay = 10},
811 },
812 {
813 .cmd_type = CMD_W,
814 .addr = 0xAA,
815 .reg = 0x3E,
816 .data = {.bytes = {0x68, 0x01}},
817 .data_len = 2,
818 },
819 {
820 .cmd_type = CMD_C,
821 .addr = 0xAA,
822 .reg = 0x60,
823 .data = {.bytes = {0xEA}},
824 .data_len = 1,
825 },
826 {
827 .cmd_type = CMD_W,
828 .addr = 0xAA,
829 .reg = 0x3E,
830 .data = {.bytes = {0x69, 0x00}},
831 .data_len = 2,
832 },
833 {
834 .cmd_type = CMD_W,
835 .addr = 0xAA,
836 .reg = 0x40,
837 .data = {.bytes = {0xFF, 0xFF, 0x0B, 0xD6, 0x7E, 0x74, 0x6D, 0xC6, 0x93, 0x0B, 0x0D, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
838 .data_len = 32,
839 },
840 {
841 .cmd_type = CMD_W,
842 .addr = 0xAA,
843 .reg = 0x60,
844 .data = {.bytes = {0xCA}},
845 .data_len = 1,
846 },
847 {
848 .cmd_type = CMD_X,
849 .data = {.delay = 10},
850 },
851 {
852 .cmd_type = CMD_W,
853 .addr = 0xAA,
854 .reg = 0x3E,
855 .data = {.bytes = {0x69, 0x00}},
856 .data_len = 2,
857 },
858 {
859 .cmd_type = CMD_C,
860 .addr = 0xAA,
861 .reg = 0x60,
862 .data = {.bytes = {0xCA}},
863 .data_len = 1,
864 },
865 {
866 .cmd_type = CMD_W,
867 .addr = 0xAA,
868 .reg = 0x3E,
869 .data = {.bytes = {0x6B, 0x00}},
870 .data_len = 2,
871 },
872 {
873 .cmd_type = CMD_W,
874 .addr = 0xAA,
875 .reg = 0x40,
876 .data = {.bytes = {0xEF, 0x05, 0x11, 0x05, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x3C, 0x00, 0x50, 0x3C, 0x00, 0x64, 0x3C, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
877 .data_len = 32,
878 },
879 {
880 .cmd_type = CMD_W,
881 .addr = 0xAA,
882 .reg = 0x60,
883 .data = {.bytes = {0x5B}},
884 .data_len = 1,
885 },
886 {
887 .cmd_type = CMD_X,
888 .data = {.delay = 10},
889 },
890 {
891 .cmd_type = CMD_W,
892 .addr = 0xAA,
893 .reg = 0x3E,
894 .data = {.bytes = {0x6B, 0x00}},
895 .data_len = 2,
896 },
897 {
898 .cmd_type = CMD_C,
899 .addr = 0xAA,
900 .reg = 0x60,
901 .data = {.bytes = {0x5B}},
902 .data_len = 1,
903 },
904 {
905 .cmd_type = CMD_W,
906 .addr = 0xAA,
907 .reg = 0x3E,
908 .data = {.bytes = {0x70, 0x00}},
909 .data_len = 2,
910 },
911 {
912 .cmd_type = CMD_W,
913 .addr = 0xAA,
914 .reg = 0x40,
915 .data = {.bytes = {0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
916 .data_len = 32,
917 },
918 {
919 .cmd_type = CMD_W,
920 .addr = 0xAA,
921 .reg = 0x60,
922 .data = {.bytes = {0xFF}},
923 .data_len = 1,
924 },
925 {
926 .cmd_type = CMD_X,
927 .data = {.delay = 10},
928 },
929 {
930 .cmd_type = CMD_W,
931 .addr = 0xAA,
932 .reg = 0x3E,
933 .data = {.bytes = {0x70, 0x00}},
934 .data_len = 2,
935 },
936 {
937 .cmd_type = CMD_C,
938 .addr = 0xAA,
939 .reg = 0x60,
940 .data = {.bytes = {0xFF}},
941 .data_len = 1,
942 },
943};
944//end of const bqfs_cmd_t bqfs_image[]
945#endif
diff --git a/drivers/power/bq27426/bqfs_cmd_type.h b/drivers/power/bq27426/bqfs_cmd_type.h
new file mode 100644
index 000000000000..b6027ac3ff8b
--- /dev/null
+++ b/drivers/power/bq27426/bqfs_cmd_type.h
@@ -0,0 +1,42 @@
1
2
3#ifndef __BQFS_CMD_TYPE__
4#define __BQFS_CMD_TYPE__
5
6
7#define CMD_MAX_DATA_SIZE 110
8#define RETRY_LIMIT 3
9#define CMD_RETRY_DELAY 100 /* in ms */
10
11#ifdef __GNUC__
12#define __PACKED __attribute__((packed))
13#else
14#error "Make sure structure cmd_t is packed"
15#endif
16
17typedef enum {
18 CMD_INVALID = 0,
19 CMD_R, /* Read */
20 CMD_W, /* Write */
21 CMD_C, /* Compare */
22 CMD_X, /* Delay */
23} cmd_type_t;
24
25/*
26 * DO NOT change the order of fields - particularly reg
27 * should be immediately followed by data
28 */
29typedef struct {
30 cmd_type_t cmd_type;
31 u8 addr;
32 u8 reg;
33 union {
34 u8 bytes[CMD_MAX_DATA_SIZE + 1];
35 u16 delay;
36 } data;
37 u8 data_len;
38 u16 line_num;
39} __PACKED bqfs_cmd_t;
40
41
42#endif