| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198 |
- /* Copyright Statement:
- *
- * This software/firmware and related documentation ("MediaTek Software") are
- * protected under relevant copyright laws. The information contained herein
- * is confidential and proprietary to MediaTek Inc. and/or its licensors.
- * Without the prior written permission of MediaTek inc. and/or its licensors,
- * any reproduction, modification, use or disclosure of MediaTek Software,
- * and information contained herein, in whole or in part, shall be strictly prohibited.
- */
- /* MediaTek Inc. (C) 2018. All rights reserved.
- *
- * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
- * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
- * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
- * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
- * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
- * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
- * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
- * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
- * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
- * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
- * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
- * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
- * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
- * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
- * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
- * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
- */
- #include <platform/mt_typedefs.h>
- #include <platform/errno.h>
- #include <platform/mt_i2c.h>
- #include <platform/mt_gpio.h>
- #include "rt9471.h"
- #include "mtk_charger_intf.h"
- #define RT9471_LK_DRV_VERSION "1.0.3_MTK"
- /* ================= */
- /* Internal variable */
- /* ================= */
- enum rt9471_stat_idx {
- RT9471_STATIDX_STAT0 = 0,
- RT9471_STATIDX_STAT1,
- RT9471_STATIDX_STAT2,
- RT9471_STATIDX_STAT3,
- RT9471_STATIDX_MAX,
- };
- enum rt9471_irq_idx {
- RT9471_IRQIDX_IRQ0 = 0,
- RT9471_IRQIDX_IRQ1,
- RT9471_IRQIDX_IRQ2,
- RT9471_IRQIDX_IRQ3,
- RT9471_IRQIDX_MAX,
- };
- enum rt9471_ic_stat {
- RT9471_ICSTAT_SLEEP = 0,
- RT9471_ICSTAT_VBUSRDY,
- RT9471_ICSTAT_TRICKLECHG,
- RT9471_ICSTAT_PRECHG,
- RT9471_ICSTAT_FASTCHG,
- RT9471_ICSTAT_IEOC,
- RT9471_ICSTAT_BGCHG,
- RT9471_ICSTAT_CHGDONE,
- RT9471_ICSTAT_CHGFAULT,
- RT9471_ICSTAT_OTG = 15,
- RT9471_ICSTAT_MAX,
- };
- static const char *rt9471_ic_stat_name[RT9471_ICSTAT_MAX] = {
- "hz/sleep", "ready", "trickle-charge", "pre-charge",
- "fast-charge", "ieoc-charge", "background-charge",
- "done", "fault", "RESERVED", "RESERVED", "RESERVED",
- "RESERVED", "RESERVED", "RESERVED", "OTG",
- };
- enum rt9471_mivr_track {
- RT9471_MIVRTRACK_REG = 0,
- RT9471_MIVRTRACK_VBAT_200MV,
- RT9471_MIVRTRACK_VBAT_250MV,
- RT9471_MIVRTRACK_VBAT_300MV,
- RT9471_MIVRTRACK_MAX,
- };
- struct rt9471_desc {
- u32 vac_ovp;
- u32 mivr;
- u32 aicr;
- u32 cv;
- u32 ichg;
- u32 ieoc;
- u32 safe_tmr;
- u32 wdt;
- u32 mivr_track;
- bool en_safe_tmr;
- bool en_te;
- bool en_jeita;
- bool ceb_invert;
- bool dis_i2c_tout;
- bool en_qon_rst;
- bool auto_aicr;
- };
- static struct rt9471_desc rt9471_default_desc = {
- .vac_ovp = 14000000,
- .mivr = 4400000,
- .aicr = 500000,
- .cv = 4350000,
- .ichg = 1000000,
- .ieoc = 200000,
- .safe_tmr = 10,
- .wdt = 40,
- .mivr_track = RT9471_MIVRTRACK_REG,
- .en_safe_tmr = true,
- .en_te = true,
- .en_jeita = false,
- .ceb_invert = false,
- .dis_i2c_tout = false,
- .en_qon_rst = true,
- .auto_aicr = false,
- };
- static const u8 rt9471_irq_maskall[RT9471_IRQIDX_MAX] = {
- 0xFF, 0xFF, 0xFF, 0xFF,
- };
- static const u32 rt9471_vac_ovp[] = {
- 5800000, 6500000, 10900000, 14000000,
- };
- static const u32 rt9471_wdt[] = {
- 0, 40, 80, 160,
- };
- static const u8 rt9471_val_en_hidden_mode[] = {
- 0x69, 0x96,
- };
- struct rt9471_chip {
- struct mtk_charger_info mchr_info;
- struct mt_i2c_t i2c;
- int i2c_log_level;
- int hidden_mode_cnt;
- u8 chip_rev;
- struct rt9471_desc *desc;
- u32 ceb_gpio;
- bool wkard_en;
- };
- static const u8 rt9471_reg_addr[] = {
- RT9471_REG_OTGCFG,
- RT9471_REG_TOP,
- RT9471_REG_FUNCTION,
- RT9471_REG_IBUS,
- RT9471_REG_VBUS,
- RT9471_REG_PRECHG,
- RT9471_REG_REGU,
- RT9471_REG_VCHG,
- RT9471_REG_ICHG,
- RT9471_REG_CHGTIMER,
- RT9471_REG_EOC,
- RT9471_REG_INFO,
- RT9471_REG_JEITA,
- RT9471_REG_PUMPEXP,
- RT9471_REG_DPDMDET,
- RT9471_REG_STATUS,
- RT9471_REG_STAT0,
- RT9471_REG_STAT1,
- RT9471_REG_STAT2,
- RT9471_REG_STAT3,
- /* Skip IRQs to prevent reading clear while dumping registers */
- RT9471_REG_MASK0,
- RT9471_REG_MASK1,
- RT9471_REG_MASK2,
- RT9471_REG_MASK3,
- };
- static int rt9471_i2c_read_byte(struct rt9471_chip *chip, u8 cmd, u8 *data)
- {
- int ret = 0;
- u8 regval = cmd;
- struct mt_i2c_t *i2c = &chip->i2c;
- ret = i2c_write_read(i2c, ®val, 1, 1);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s reg0x%02X fail(%d)\n",
- __func__, cmd, ret);
- else {
- dprintf(SPEW, "%s reg0x%02X = 0x%02X\n", __func__, cmd, regval);
- *data = regval;
- }
- return ret;
- }
- static int rt9471_i2c_write_byte(struct rt9471_chip *chip, u8 cmd, u8 data)
- {
- int ret = 0;
- u8 write_buf[2] = {cmd, data};
- struct mt_i2c_t *i2c = &chip->i2c;
- ret = i2c_write(i2c, write_buf, 2);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s reg0x%02X = 0x%02X fail(%d)\n",
- __func__, cmd, data, ret);
- else
- dprintf(SPEW, "%s reg0x%02X = 0x%02X\n", __func__, cmd, data);
- return ret;
- }
- static int rt9471_i2c_block_read(struct rt9471_chip *chip, u8 cmd, u32 len,
- u8 *data)
- {
- int ret = 0, i = 0;
- struct mt_i2c_t *i2c = &chip->i2c;
- data[0] = cmd;
- ret = i2c_write_read(i2c, data, 1, len);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s reg0x%02X..reg0x%02X fail(%d)\n",
- __func__, cmd, cmd + len - 1, ret);
- else
- for (i = 0; i <= len - 1; i++)
- dprintf(SPEW, "%s reg0x%02X = 0x%02X\n",
- __func__, cmd + i, data[i]);
- return ret;
- }
- static int rt9471_i2c_block_write(struct rt9471_chip *chip, u8 cmd, u32 len,
- const u8 *data)
- {
- int ret = 0, i = 0;
- u8 write_buf[len + 1];
- struct mt_i2c_t *i2c = &chip->i2c;
- write_buf[0] = cmd;
- memcpy(&write_buf[1], data, len);
- ret = i2c_write(i2c, write_buf, len + 1);
- if (ret != I2C_OK) {
- dprintf(CRITICAL, "%s fail(%d)\n", __func__, ret);
- for (i = 0; i <= len - 1; i++)
- dprintf(CRITICAL, "%s reg0x%02X = 0x%02X\n",
- __func__, cmd + i, data[i]);
- } else
- for (i = 0; i <= len - 1; i++)
- dprintf(SPEW, "%s reg0x%02X = 0x%02X\n",
- __func__, cmd + i, data[i]);
- return ret;
- }
- static int rt9471_i2c_test_bit(struct rt9471_chip *chip, u8 cmd, u8 shift,
- bool *is_one)
- {
- int ret = 0;
- u8 regval = 0;
- ret = rt9471_i2c_read_byte(chip, cmd, ®val);
- if (ret != I2C_OK) {
- *is_one = false;
- return ret;
- }
- regval &= 1 << shift;
- *is_one = (regval ? true : false);
- return ret;
- }
- static int rt9471_i2c_update_bits(struct rt9471_chip *chip, u8 cmd, u8 data,
- u8 mask)
- {
- int ret = 0;
- u8 regval = 0;
- ret = rt9471_i2c_read_byte(chip, cmd, ®val);
- if (ret != I2C_OK)
- return ret;
- regval &= ~mask;
- regval |= (data & mask);
- return rt9471_i2c_write_byte(chip, cmd, regval);
- }
- static inline int rt9471_set_bit(struct rt9471_chip *chip, u8 cmd, u8 mask)
- {
- return rt9471_i2c_update_bits(chip, cmd, mask, mask);
- }
- static inline int rt9471_clr_bit(struct rt9471_chip *chip, u8 cmd, u8 mask)
- {
- return rt9471_i2c_update_bits(chip, cmd, 0x00, mask);
- }
- static inline u8 rt9471_closest_reg(u32 min, u32 max, u32 step, u32 target)
- {
- if (target < min)
- return 0;
- if (target >= max)
- target = max;
- return (target - min) / step;
- }
- static inline u8 rt9471_closest_reg_via_tbl(const u32 *tbl, u32 tbl_size,
- u32 target)
- {
- u32 i = 0;
- if (target < tbl[0])
- return 0;
- for (i = 0; i < tbl_size - 1; i++) {
- if (target >= tbl[i] && target < tbl[i + 1])
- return i;
- }
- return tbl_size - 1;
- }
- static inline u32 rt9471_closest_value(u32 min, u32 max, u32 step, u8 regval)
- {
- u32 val = 0;
- val = min + regval * step;
- if (val > max)
- val = max;
- return val;
- }
- static int rt9471_enable_hidden_mode(struct rt9471_chip *chip, bool en)
- {
- int ret = 0;
- if (en) {
- if (chip->hidden_mode_cnt == 0) {
- ret = rt9471_i2c_block_write(chip, RT9471_REG_PASSCODE1,
- ARRAY_SIZE(rt9471_val_en_hidden_mode),
- rt9471_val_en_hidden_mode);
- if (ret != I2C_OK)
- goto err;
- }
- chip->hidden_mode_cnt++;
- } else {
- if (chip->hidden_mode_cnt == 1) { /* last one */
- ret = rt9471_i2c_write_byte(chip, RT9471_REG_PASSCODE1,
- 0x00);
- if (ret != I2C_OK)
- goto err;
- }
- chip->hidden_mode_cnt--;
- }
- dprintf(chip->i2c_log_level, "%s en = %d, cnt = %d\n",
- __func__, en, chip->hidden_mode_cnt);
- goto out;
- err:
- dprintf(CRITICAL, "%s en = %d fail(%d)\n", __func__, en, ret);
- out:
- return ret;
- }
- static int __rt9471_get_ic_stat(struct rt9471_chip *chip,
- enum rt9471_ic_stat *stat)
- {
- int ret = 0;
- u8 regval = 0;
- ret = rt9471_i2c_read_byte(chip, RT9471_REG_STATUS, ®val);
- if (ret != I2C_OK)
- return ret;
- *stat = (regval & RT9471_ICSTAT_MASK) >> RT9471_ICSTAT_SHIFT;
- return ret;
- }
- static int __rt9471_get_mivr(struct rt9471_chip *chip, u32 *mivr)
- {
- int ret = 0;
- u8 regval = 0;
- ret = rt9471_i2c_read_byte(chip, RT9471_REG_VBUS, ®val);
- if (ret != I2C_OK)
- return ret;
- regval = (regval & RT9471_MIVR_MASK) >> RT9471_MIVR_SHIFT;
- *mivr = rt9471_closest_value(RT9471_MIVR_MIN, RT9471_MIVR_MAX,
- RT9471_MIVR_STEP, regval);
- return ret;
- }
- static int __rt9471_get_aicr(struct rt9471_chip *chip, u32 *aicr)
- {
- int ret = 0;
- u8 regval = 0;
- ret = rt9471_i2c_read_byte(chip, RT9471_REG_IBUS, ®val);
- if (ret != I2C_OK)
- return ret;
- regval = (regval & RT9471_AICR_MASK) >> RT9471_AICR_SHIFT;
- *aicr = rt9471_closest_value(RT9471_AICR_MIN, RT9471_AICR_MAX,
- RT9471_AICR_STEP, regval);
- if (*aicr > RT9471_AICR_MIN && *aicr < RT9471_AICR_MAX)
- *aicr -= RT9471_AICR_STEP;
- return ret;
- }
- static int __rt9471_get_cv(struct rt9471_chip *chip, u32 *cv)
- {
- int ret = 0;
- u8 regval = 0;
- ret = rt9471_i2c_read_byte(chip, RT9471_REG_VCHG, ®val);
- if (ret != I2C_OK)
- return ret;
- regval = (regval & RT9471_CV_MASK) >> RT9471_CV_SHIFT;
- *cv = rt9471_closest_value(RT9471_CV_MIN, RT9471_CV_MAX, RT9471_CV_STEP,
- regval);
- return ret;
- }
- static int __rt9471_get_ichg(struct rt9471_chip *chip, u32 *ichg)
- {
- int ret = 0;
- u8 regval = 0;
- ret = rt9471_i2c_read_byte(chip, RT9471_REG_ICHG, ®val);
- if (ret != I2C_OK)
- return ret;
- regval = (regval & RT9471_ICHG_MASK) >> RT9471_ICHG_SHIFT;
- *ichg = rt9471_closest_value(RT9471_ICHG_MIN, RT9471_ICHG_MAX,
- RT9471_ICHG_STEP, regval);
- return ret;
- }
- static int __rt9471_get_ieoc(struct rt9471_chip *chip, u32 *ieoc)
- {
- int ret = 0;
- u8 regval = 0;
- ret = rt9471_i2c_read_byte(chip, RT9471_REG_EOC, ®val);
- if (ret != I2C_OK)
- return ret;
- regval = (regval & RT9471_IEOC_MASK) >> RT9471_IEOC_SHIFT;
- *ieoc = rt9471_closest_value(RT9471_IEOC_MIN, RT9471_IEOC_MAX,
- RT9471_IEOC_STEP, regval);
- return ret;
- }
- static int __rt9471_is_chg_enabled(struct rt9471_chip *chip, bool *en)
- {
- return rt9471_i2c_test_bit(chip, RT9471_REG_FUNCTION,
- RT9471_CHG_EN_SHIFT, en);
- }
- static int __rt9471_enable_safe_tmr(struct rt9471_chip *chip, bool en)
- {
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- return (en ? rt9471_set_bit : rt9471_clr_bit)
- (chip, RT9471_REG_CHGTIMER, RT9471_SAFETMR_EN_MASK);
- }
- static int __rt9471_enable_te(struct rt9471_chip *chip, bool en)
- {
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- return (en ? rt9471_set_bit : rt9471_clr_bit)
- (chip, RT9471_REG_EOC, RT9471_TE_MASK);
- }
- static int __rt9471_enable_jeita(struct rt9471_chip *chip, bool en)
- {
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- return (en ? rt9471_set_bit : rt9471_clr_bit)
- (chip, RT9471_REG_JEITA, RT9471_JEITA_EN_MASK);
- }
- static int __rt9471_disable_i2c_tout(struct rt9471_chip *chip, bool en)
- {
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- return (en ? rt9471_set_bit : rt9471_clr_bit)
- (chip, RT9471_REG_TOP, RT9471_DISI2CTO_MASK);
- }
- static int __rt9471_enable_qon_rst(struct rt9471_chip *chip, bool en)
- {
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- return (en ? rt9471_set_bit : rt9471_clr_bit)
- (chip, RT9471_REG_TOP, RT9471_QONRST_MASK);
- }
- static int __rt9471_enable_autoaicr(struct rt9471_chip *chip, bool en)
- {
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- return (en ? rt9471_set_bit : rt9471_clr_bit)
- (chip, RT9471_REG_IBUS, RT9471_AUTOAICR_MASK);
- }
- static int __rt9471_enable_hz(struct rt9471_chip *chip, bool en)
- {
- int ret = 0;
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- ret = rt9471_enable_hidden_mode(chip, true);
- if (ret != I2C_OK)
- return ret;
- /* Use force HZ */
- ret = (en ? rt9471_set_bit : rt9471_clr_bit)
- (chip, RT9471_REG_HIDDEN_2, RT9471_FORCE_HZ_MASK);
- rt9471_enable_hidden_mode(chip, false);
- return ret;
- }
- static int __rt9471_enable_chg(struct rt9471_chip *chip, bool en)
- {
- struct rt9471_desc *desc = chip->desc;
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- if (chip->ceb_gpio != U32_MAX)
- mt_set_gpio_out(chip->ceb_gpio, desc->ceb_invert ? en : !en);
- return (en ? rt9471_set_bit : rt9471_clr_bit)
- (chip, RT9471_REG_FUNCTION, RT9471_CHG_EN_MASK);
- }
- static int __rt9471_set_vac_ovp(struct rt9471_chip *chip, u32 vac_ovp)
- {
- u8 regval = 0;
- regval = rt9471_closest_reg_via_tbl(rt9471_vac_ovp,
- ARRAY_SIZE(rt9471_vac_ovp),
- vac_ovp);
- dprintf(chip->i2c_log_level, "%s vac_ovp = %d(0x%02X)\n",
- __func__, vac_ovp, regval);
- return rt9471_i2c_update_bits(chip, RT9471_REG_VBUS,
- regval << RT9471_VAC_OVP_SHIFT,
- RT9471_VAC_OVP_MASK);
- }
- static int __rt9471_set_mivr(struct rt9471_chip *chip, u32 mivr)
- {
- u8 regval = 0;
- regval = rt9471_closest_reg(RT9471_MIVR_MIN, RT9471_MIVR_MAX,
- RT9471_MIVR_STEP, mivr);
- dprintf(chip->i2c_log_level, "%s mivr = %d(0x%02X)\n",
- __func__, mivr, regval);
- return rt9471_i2c_update_bits(chip, RT9471_REG_VBUS,
- regval << RT9471_MIVR_SHIFT,
- RT9471_MIVR_MASK);
- }
- static int __rt9471_set_aicr(struct rt9471_chip *chip, u32 aicr)
- {
- u8 regval = 0;
- regval = rt9471_closest_reg(RT9471_AICR_MIN, RT9471_AICR_MAX,
- RT9471_AICR_STEP, aicr);
- /* 0 & 1 are both 50mA */
- if (aicr < RT9471_AICR_MAX)
- regval += 1;
- dprintf(chip->i2c_log_level, "%s aicr = %d(0x%02X)\n",
- __func__, aicr, regval);
- return rt9471_i2c_update_bits(chip, RT9471_REG_IBUS,
- regval << RT9471_AICR_SHIFT,
- RT9471_AICR_MASK);
- }
- static int __rt9471_set_cv(struct rt9471_chip *chip, u32 cv)
- {
- u8 regval = 0;
- regval = rt9471_closest_reg(RT9471_CV_MIN, RT9471_CV_MAX,
- RT9471_CV_STEP, cv);
- dprintf(chip->i2c_log_level, "%s cv = %d(0x%02X)\n",
- __func__, cv, regval);
- return rt9471_i2c_update_bits(chip, RT9471_REG_VCHG,
- regval << RT9471_CV_SHIFT,
- RT9471_CV_MASK);
- }
- static int __rt9471_set_ichg(struct rt9471_chip *chip, u32 ichg)
- {
- u8 regval = 0;
- regval = rt9471_closest_reg(RT9471_ICHG_MIN, RT9471_ICHG_MAX,
- RT9471_ICHG_STEP, ichg);
- dprintf(chip->i2c_log_level, "%s ichg = %d(0x%02X)\n",
- __func__, ichg, regval);
- return rt9471_i2c_update_bits(chip, RT9471_REG_ICHG,
- regval << RT9471_ICHG_SHIFT,
- RT9471_ICHG_MASK);
- }
- static int __rt9471_set_ieoc(struct rt9471_chip *chip, u32 ieoc)
- {
- u8 regval = 0;
- regval = rt9471_closest_reg(RT9471_IEOC_MIN, RT9471_IEOC_MAX,
- RT9471_IEOC_STEP, ieoc);
- dprintf(chip->i2c_log_level, "%s ieoc = %d(0x%02X)\n",
- __func__, ieoc, regval);
- return rt9471_i2c_update_bits(chip, RT9471_REG_EOC,
- regval << RT9471_IEOC_SHIFT,
- RT9471_IEOC_MASK);
- }
- static int __rt9471_set_safe_tmr(struct rt9471_chip *chip, u32 hr)
- {
- u8 regval = 0;
- regval = rt9471_closest_reg(RT9471_SAFETMR_MIN, RT9471_SAFETMR_MAX,
- RT9471_SAFETMR_STEP, hr);
- dprintf(chip->i2c_log_level, "%s time = %d(0x%02X)\n",
- __func__, hr, regval);
- return rt9471_i2c_update_bits(chip, RT9471_REG_CHGTIMER,
- regval << RT9471_SAFETMR_SHIFT,
- RT9471_SAFETMR_MASK);
- }
- static int __rt9471_set_wdt(struct rt9471_chip *chip, u32 sec)
- {
- u8 regval = 0;
- /* 40s is the minimum, set to 40 except sec == 0 */
- if (sec <= 40 && sec > 0)
- sec = 40;
- regval = rt9471_closest_reg_via_tbl(rt9471_wdt, ARRAY_SIZE(rt9471_wdt),
- sec);
- dprintf(chip->i2c_log_level, "%s time = %d(0x%02X)\n",
- __func__, sec, regval);
- return rt9471_i2c_update_bits(chip, RT9471_REG_TOP,
- regval << RT9471_WDT_SHIFT,
- RT9471_WDT_MASK);
- }
- static int __rt9471_set_mivrtrack(struct rt9471_chip *chip, u32 mivr_track)
- {
- if (mivr_track >= RT9471_MIVRTRACK_MAX)
- mivr_track = RT9471_MIVRTRACK_VBAT_300MV;
- dprintf(chip->i2c_log_level, "%s mivrtrack = %d\n",
- __func__, mivr_track);
- return rt9471_i2c_update_bits(chip, RT9471_REG_VBUS,
- mivr_track << RT9471_MIVRTRACK_SHIFT,
- RT9471_MIVRTRACK_MASK);
- }
- static int __rt9471_kick_wdt(struct rt9471_chip *chip)
- {
- dprintf(chip->i2c_log_level, "%s\n", __func__);
- return rt9471_set_bit(chip, RT9471_REG_TOP, RT9471_WDTCNTRST_MASK);
- }
- static bool rt9471_is_hw_exist(struct rt9471_chip *chip)
- {
- int ret = 0;
- u8 info = 0, dev_id = 0, dev_rev = 0;
- ret = rt9471_i2c_read_byte(chip, RT9471_REG_INFO, &info);
- if (ret != I2C_OK) {
- dprintf(CRITICAL, "%s get devinfo fail(%d)\n", __func__, ret);
- return false;
- }
- dev_id = (info & RT9471_DEVID_MASK) >> RT9471_DEVID_SHIFT;
- switch (dev_id) {
- case RT9470_DEVID:
- case RT9470D_DEVID:
- case RT9471_DEVID:
- case RT9471D_DEVID:
- break;
- default:
- dprintf(CRITICAL, "%s incorrect devid 0x%02X\n",
- __func__, dev_id);
- return false;
- }
- dev_rev = (info & RT9471_DEVREV_MASK) >> RT9471_DEVREV_SHIFT;
- dprintf(chip->i2c_log_level, "%s id = 0x%02X, rev = 0x%02X\n",
- __func__, dev_id, dev_rev);
- chip->mchr_info.device_id = dev_rev;
- return true;
- }
- static int rt9471_reset_register(struct rt9471_chip *chip)
- {
- int ret = 0;
- dprintf(chip->i2c_log_level, "%s\n", __func__);
- ret = rt9471_set_bit(chip, RT9471_REG_INFO, RT9471_REGRST_MASK);
- if (ret != I2C_OK)
- return ret;
- ret = __rt9471_enable_autoaicr(chip, false);
- if (ret != I2C_OK)
- return ret;
- return __rt9471_set_wdt(chip, 0);
- }
- static int rt9471_sw_workaround(struct rt9471_chip *chip)
- {
- int ret = 0;
- u8 regval = 0;
- dprintf(chip->i2c_log_level, "%s\n", __func__);
- ret = rt9471_enable_hidden_mode(chip, true);
- if (ret != I2C_OK)
- return ret;
- ret = rt9471_i2c_read_byte(chip, RT9471_REG_HIDDEN_0, ®val);
- if (ret != I2C_OK)
- goto out;
- chip->chip_rev = (regval & RT9471_CHIP_REV_MASK) >>
- RT9471_CHIP_REV_SHIFT;
- dprintf(chip->i2c_log_level, "%s chip_rev = %d\n",
- __func__, chip->chip_rev);
- out:
- rt9471_enable_hidden_mode(chip, false);
- return ret;
- }
- static int rt9471_init_setting(struct rt9471_chip *chip)
- {
- int ret = 0;
- struct rt9471_desc *desc = chip->desc;
- u8 evt[RT9471_IRQIDX_MAX] = {0};
- dprintf(chip->i2c_log_level, "%s\n", __func__);
- /* Mask all IRQs */
- ret = rt9471_i2c_block_write(chip, RT9471_REG_MASK0,
- ARRAY_SIZE(rt9471_irq_maskall),
- rt9471_irq_maskall);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s mask irq fail(%d)\n", __func__, ret);
- /* Clear all IRQs */
- ret = rt9471_i2c_block_read(chip, RT9471_REG_IRQ0, RT9471_IRQIDX_MAX,
- evt);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s clear irq fail(%d)\n", __func__, ret);
- ret = __rt9471_set_vac_ovp(chip, desc->vac_ovp);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s set vac ovp fail(%d)\n", __func__, ret);
- ret = __rt9471_set_mivr(chip, desc->mivr);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s set mivr fail(%d)\n", __func__, ret);
- ret = __rt9471_set_aicr(chip, desc->aicr);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s set aicr fail(%d)\n", __func__, ret);
- ret = __rt9471_set_cv(chip, desc->cv);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s set cv fail(%d)\n", __func__, ret);
- ret = __rt9471_set_ichg(chip, desc->ichg);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s set ichg fail(%d)\n", __func__, ret);
- ret = __rt9471_set_ieoc(chip, desc->ieoc);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s set ieoc fail(%d)\n", __func__, ret);
- ret = __rt9471_set_safe_tmr(chip, desc->safe_tmr);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s set safe tmr fail(%d)\n", __func__, ret);
- ret = __rt9471_set_mivrtrack(chip, desc->mivr_track);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s set mivrtrack fail(%d)\n",
- __func__, ret);
- ret = __rt9471_enable_safe_tmr(chip, desc->en_safe_tmr);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s en safe tmr fail(%d)\n", __func__, ret);
- ret = __rt9471_enable_te(chip, desc->en_te);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s en te fail(%d)\n", __func__, ret);
- ret = __rt9471_enable_jeita(chip, desc->en_jeita);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s en jeita fail(%d)\n", __func__, ret);
- ret = __rt9471_disable_i2c_tout(chip, desc->dis_i2c_tout);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s dis i2c tout fail(%d)\n", __func__, ret);
- ret = __rt9471_enable_qon_rst(chip, desc->en_qon_rst);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s en qon rst fail(%d)\n", __func__, ret);
- ret = __rt9471_enable_autoaicr(chip, desc->auto_aicr);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s en autoaicr fail(%d)\n", __func__, ret);
- ret = rt9471_sw_workaround(chip);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s sw workaround fail(%d)\n", __func__, ret);
- return 0;
- }
- /* =========================================================== */
- /* The following is implementation for interface of rt_charger */
- /* =========================================================== */
- static int rt9471_dump_register(struct mtk_charger_info *mchr_info)
- {
- int ret = 0, i = 0;
- u32 mivr = 0, aicr = 0, cv = 0, ichg = 0, ieoc = 0;
- bool chg_en = 0;
- enum rt9471_ic_stat ic_stat = RT9471_ICSTAT_SLEEP;
- u8 stats[RT9471_STATIDX_MAX] = {0}, regval = 0, hidden_2 = 0;
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- ret = __rt9471_kick_wdt(chip);
- ret = __rt9471_get_mivr(chip, &mivr);
- ret = __rt9471_get_aicr(chip, &aicr);
- ret = __rt9471_get_cv(chip, &cv);
- ret = __rt9471_get_ichg(chip, &ichg);
- ret = __rt9471_get_ieoc(chip, &ieoc);
- ret = __rt9471_is_chg_enabled(chip, &chg_en);
- ret = __rt9471_get_ic_stat(chip, &ic_stat);
- ret = rt9471_i2c_block_read(chip, RT9471_REG_STAT0, RT9471_STATIDX_MAX,
- stats);
- ret = rt9471_i2c_read_byte(chip, RT9471_REG_HIDDEN_2, &hidden_2);
- if (ic_stat == RT9471_ICSTAT_CHGFAULT) {
- for (i = 0; i < ARRAY_SIZE(rt9471_reg_addr); i++) {
- ret = rt9471_i2c_read_byte(chip, rt9471_reg_addr[i],
- ®val);
- if (ret != I2C_OK)
- continue;
- dprintf(CRITICAL, "%s reg0x%02X = 0x%02X\n",
- __func__, rt9471_reg_addr[i], regval);
- }
- }
- dprintf(chip->i2c_log_level, "%s MIVR = %dmV, AICR = %dmA\n",
- __func__, mivr / 1000, aicr / 1000);
- dprintf(chip->i2c_log_level, "%s CV = %dmV, ICHG = %dmA, IEOC = %dmA\n",
- __func__, cv / 1000, ichg / 1000, ieoc / 1000);
- dprintf(chip->i2c_log_level, "%s CHG_EN = %d, IC_STAT = %s\n",
- __func__, chg_en, rt9471_ic_stat_name[ic_stat]);
- dprintf(chip->i2c_log_level,
- "%s STAT0 = 0x%02X, STAT1 = 0x%02X\n", __func__,
- stats[RT9471_STATIDX_STAT0], stats[RT9471_STATIDX_STAT1]);
- dprintf(chip->i2c_log_level,
- "%s STAT2 = 0x%02X, STAT3 = 0x%02X\n", __func__,
- stats[RT9471_STATIDX_STAT2], stats[RT9471_STATIDX_STAT3]);
- dprintf(chip->i2c_log_level, "%s HIDDEN_2 = 0x%02X\n",
- __func__, hidden_2);
- return 0;
- }
- static int rt9471_enable_charging(struct mtk_charger_info *mchr_info, bool en)
- {
- int ret = 0;
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- return __rt9471_enable_chg(chip, en);
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- if (en) {
- ret = __rt9471_set_wdt(chip, chip->desc->wdt);
- if (ret != I2C_OK) {
- dprintf(CRITICAL, "%s set wdt fail(%d)\n",
- __func__, ret);
- return ret;
- }
- }
- ret = __rt9471_enable_chg(chip, en);
- if (ret != I2C_OK) {
- dprintf(CRITICAL, "%s en chg fail(%d)\n", __func__, ret);
- return ret;
- }
- if (!en) {
- ret = __rt9471_set_wdt(chip, 0);
- if (ret != I2C_OK)
- dprintf(CRITICAL, "%s set wdt fail(%d)\n",
- __func__, ret);
- }
- return ret;
- }
- static int rt9471_set_mivr(struct mtk_charger_info *mchr_info, u32 mivr)
- {
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- return __rt9471_set_mivr(chip, mivr * 1000);
- }
- static int rt9471_get_aicr(struct mtk_charger_info *mchr_info, u32 *aicr)
- {
- int ret = 0;
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- ret = __rt9471_get_aicr(chip, aicr);
- *aicr /= 1000; /* uA --> mA */
- return ret;
- }
- static int rt9471_set_aicr(struct mtk_charger_info *mchr_info, u32 aicr)
- {
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- return __rt9471_set_aicr(chip, aicr * 1000);
- }
- static int rt9471_get_ichg(struct mtk_charger_info *mchr_info, u32 *ichg)
- {
- int ret = 0;
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- ret = __rt9471_get_ichg(chip, ichg);
- *ichg /= 1000; /* uA --> mA */
- return ret;
- }
- static int rt9471_set_ichg(struct mtk_charger_info *mchr_info, u32 ichg)
- {
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- return __rt9471_set_ichg(chip, ichg * 1000);
- }
- static int rt9471_enable_power_path(struct mtk_charger_info *mchr_info, bool en)
- {
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- dprintf(chip->i2c_log_level, "%s en = %d\n", __func__, en);
- return __rt9471_enable_hz(chip, !en);
- }
- static int rt9471_reset_pumpx(struct mtk_charger_info *mchr_info, bool en)
- {
- int ret = 0;
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- struct rt9471_desc *desc = chip->desc;
- dprintf(chip->i2c_log_level, "%s en = %d, chip_rev = %d\n",
- __func__, en, chip->chip_rev);
- if (chip->chip_rev < 4)
- return -EOPNOTSUPP;
- if (en && desc->auto_aicr) {
- ret = __rt9471_enable_autoaicr(chip, false);
- if (ret != I2C_OK)
- return ret;
- }
- /* 50mA */
- ret = __rt9471_set_aicr(chip, en ? 50000 : desc->aicr);
- if (ret != I2C_OK)
- return ret;
- if (!en && desc->auto_aicr)
- ret = __rt9471_enable_autoaicr(chip, true);
- return ret;
- }
- static int rt9471_enable_wdt(struct mtk_charger_info *mchr_info, bool en)
- {
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- return __rt9471_set_wdt(chip, en ? chip->desc->wdt : 0);
- }
- static int rt9471_reset_wdt(struct mtk_charger_info *mchr_info)
- {
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- return __rt9471_kick_wdt(chip);
- }
- static int rt9471_sw_reset(struct mtk_charger_info *mchr_info)
- {
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- return rt9471_reset_register(chip);
- }
- static inline int rt9471_fix_current_accuracy(struct rt9471_chip *chip, bool en)
- {
- int ret = 0;
- if (!(chip->wkard_en ^ en))
- return ret;
- ret = rt9471_enable_hidden_mode(chip, true);
- if (ret != I2C_OK)
- return ret;
- ret = rt9471_i2c_write_byte(chip, RT9471_REG_BUCK_HDEN4,
- en ? 0x77 : 0x71);
- if (ret != I2C_OK)
- goto out;
- ret = rt9471_i2c_write_byte(chip, RT9471_REG_BUCK_HDEN3,
- en ? 0xC0 : 0xF0);
- if (ret != I2C_OK)
- goto out;
- chip->wkard_en = en;
- out:
- rt9471_enable_hidden_mode(chip, false);
- return ret;
- }
- static int rt9471_check_charging_mode(struct mtk_charger_info *mchr_info)
- {
- int ret = 0;
- struct rt9471_chip *chip = (struct rt9471_chip *)mchr_info;
- static enum rt9471_ic_stat pre_stat = RT9471_ICSTAT_SLEEP;
- enum rt9471_ic_stat cur_stat = RT9471_ICSTAT_SLEEP;
- dprintf(chip->i2c_log_level, "%s\n", __func__);
- ret = __rt9471_get_ic_stat(chip, &cur_stat);
- if (ret != I2C_OK)
- goto out;
- dprintf(chip->i2c_log_level, "%s in %s stat, previously in %s stat\n",
- __func__, rt9471_ic_stat_name[cur_stat],
- rt9471_ic_stat_name[pre_stat]);
- if (cur_stat == pre_stat)
- goto out;
- switch (cur_stat) {
- case RT9471_ICSTAT_TRICKLECHG:
- case RT9471_ICSTAT_PRECHG:
- ret = rt9471_fix_current_accuracy(chip, true);
- if (ret != I2C_OK) {
- dprintf(CRITICAL, "%s fix current accuracy fail(%d)\n",
- __func__, ret);
- goto out;
- }
- break;
- default:
- ret = rt9471_fix_current_accuracy(chip, false);
- if (ret != I2C_OK) {
- dprintf(CRITICAL, "%s fix current accuracy fail(%d)\n",
- __func__, ret);
- goto out;
- }
- break;
- }
- pre_stat = cur_stat;
- out:
- rt9471_dump_register(mchr_info);
- return ret;
- }
- static struct mtk_charger_ops rt9471_mchr_ops = {
- .dump_register = rt9471_dump_register,
- .enable_charging = rt9471_enable_charging,
- .set_mivr = rt9471_set_mivr,
- .get_aicr = rt9471_get_aicr,
- .set_aicr = rt9471_set_aicr,
- .get_ichg = rt9471_get_ichg,
- .set_ichg = rt9471_set_ichg,
- .enable_power_path = rt9471_enable_power_path,
- .reset_pumpx = rt9471_reset_pumpx,
- .enable_wdt = rt9471_enable_wdt,
- .reset_wdt = rt9471_reset_wdt,
- .sw_reset = rt9471_sw_reset,
- .check_charging_mode = rt9471_check_charging_mode,
- };
- /* Info of primary charger */
- static struct rt9471_chip g_rt9471_chip = {
- .mchr_info = {
- .name = "primary_charger",
- .alias_name = "rt9471_charger",
- .device_id = -1,
- .mchr_ops = &rt9471_mchr_ops,
- },
- .i2c = {
- .id = I2C7,
- .addr = RT9471_SLAVE_ADDR,
- .mode = FS_MODE,
- .speed = 400,
- },
- .i2c_log_level = INFO,
- .hidden_mode_cnt = 0,
- .chip_rev = 0,
- .desc = &rt9471_default_desc,
- .ceb_gpio = U32_MAX,
- .wkard_en = false,
- };
- int rt9471_probe(void)
- {
- int ret = 0;
- dprintf(INFO, "%s (%s)\n", __func__, RT9471_LK_DRV_VERSION);
- if (!rt9471_is_hw_exist(&g_rt9471_chip))
- return -ENODEV;
- ret = rt9471_reset_register(&g_rt9471_chip);
- if (ret != I2C_OK)
- return ret;
- ret = rt9471_init_setting(&g_rt9471_chip);
- if (ret != I2C_OK)
- return ret;
- ret = mtk_charger_set_info(&g_rt9471_chip.mchr_info);
- if (ret < 0)
- return ret;
- rt9471_dump_register(&g_rt9471_chip.mchr_info);
- dprintf(INFO, "%s successfully\n", __func__);
- return 0;
- }
- /*
- * Release Note
- * 1.0.3
- * (1) Disable Auto AICR and WDT after register reset
- *
- * 1.0.2
- * (1) Sync with Kernel Driver
- * (2) Remove unnecessary #include
- * (3) Add rt9471_reset_pumpx()
- *
- * 1.0.1
- * (1) Kick WDT in rt9471_check_charging_mode()
- * (2) Add support for RT9470/RT9470D
- * (3) Sync with Kernel Driver
- *
- * 1.0.0
- * (1) Support E2 chip
- */
|