^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (C) 2018 ROHM Semiconductors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // power-supply driver for ROHM BD70528 PMIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * BD70528 charger HW state machine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * The thermal shutdown state is not drawn. From any other state but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * battery error and suspend it is possible to go to TSD/TMP states
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * if temperature is out of bounds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * CHG_RST = H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * or CHG_EN=L
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * or (DCIN2_UVLO=L && DCIN1_UVLO=L)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * or (DCIN2_OVLO=H & DCIN1_UVKLO=L)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * +--------------+ +--------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * | Any state +-------> | Suspend |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * +--------------+ +------+-------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * CHG_EN = H && BAT_DET = H && |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * No errors (temp, bat_ov, UVLO, |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * OVLO...) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * BAT_OV or +---------v----------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * (DBAT && TTRI) | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * +-----------------+ Trickle Charge | <---------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * | +-------+------------+ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * | | ^ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * | V_BAT > VTRI_TH | | VBAT < VTRI_TH - 50mV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * | v | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * | BAT_OV or +----------+----+ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * | (DBAT && TFST) | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * | +----------------+ Fast Charge | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * | | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * v v +----+----------+ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *+----------------+ ILIM_DET=L | ^ ILIM_DET |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *| | & CV_DET=H | | or CV_DET=L |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *| Battery Error | & VBAT > | | or VBAT < VRECHG_TH |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *| | VRECHG_TH | | or IBAT > IFST/x |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *+----------------+ & IBAT < | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * IFST/x v | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * ^ | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * | +---------+-+ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * | | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * +-------------------+ Top OFF | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * BAT_OV = H or | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * (DBAT && TFST) +-----+-----+ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * Stay top-off for 15s | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * v |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * +--------+ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * | | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * | Done +-------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * +--------+ VBAT < VRECHG_TH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #include <linux/mfd/rohm-bd70528.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #include <linux/power_supply.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #include <linux/linear_range.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define CHG_STAT_SUSPEND 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define CHG_STAT_TRICKLE 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define CHG_STAT_FAST 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define CHG_STAT_TOPOFF 0xe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define CHG_STAT_DONE 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define CHG_STAT_OTP_TRICKLE 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define CHG_STAT_OTP_FAST 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define CHG_STAT_OTP_DONE 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define CHG_STAT_TSD_TRICKLE 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define CHG_STAT_TSD_FAST 0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define CHG_STAT_TSD_TOPOFF 0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define CHG_STAT_BAT_ERR 0x7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static const char *bd70528_charger_model = "BD70528";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static const char *bd70528_charger_manufacturer = "ROHM Semiconductors";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define BD_ERR_IRQ_HND(_name_, _wrn_) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static irqreturn_t bd0528_##_name_##_interrupt(int irq, void *arg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct power_supply *psy = (struct power_supply *)arg; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) power_supply_changed(psy); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dev_err(&psy->dev, (_wrn_)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return IRQ_HANDLED; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define BD_INFO_IRQ_HND(_name_, _wrn_) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static irqreturn_t bd0528_##_name_##_interrupt(int irq, void *arg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct power_supply *psy = (struct power_supply *)arg; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) power_supply_changed(psy); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dev_dbg(&psy->dev, (_wrn_)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return IRQ_HANDLED; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define BD_IRQ_HND(_name_) bd0528_##_name_##_interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct bd70528_psy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct power_supply *psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) BD_ERR_IRQ_HND(BAT_OV_DET, "Battery overvoltage detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) BD_ERR_IRQ_HND(DBAT_DET, "Dead battery detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) BD_ERR_IRQ_HND(COLD_DET, "Battery cold\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) BD_ERR_IRQ_HND(HOT_DET, "Battery hot\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) BD_ERR_IRQ_HND(CHG_TSD, "Charger thermal shutdown\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) BD_ERR_IRQ_HND(DCIN2_OV_DET, "DCIN2 overvoltage detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) BD_INFO_IRQ_HND(BAT_OV_RES, "Battery voltage back to normal\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) BD_INFO_IRQ_HND(COLD_RES, "Battery temperature back to normal\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) BD_INFO_IRQ_HND(HOT_RES, "Battery temperature back to normal\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) BD_INFO_IRQ_HND(BAT_RMV, "Battery removed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) BD_INFO_IRQ_HND(BAT_DET, "Battery detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) BD_INFO_IRQ_HND(DCIN2_OV_RES, "DCIN2 voltage back to normal\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) BD_INFO_IRQ_HND(DCIN2_RMV, "DCIN2 removed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) BD_INFO_IRQ_HND(DCIN2_DET, "DCIN2 detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) BD_INFO_IRQ_HND(DCIN1_RMV, "DCIN1 removed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) BD_INFO_IRQ_HND(DCIN1_DET, "DCIN1 detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct irq_name_pair {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) const char *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) irqreturn_t (*h)(int irq, void *arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int bd70528_get_irqs(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct bd70528_psy *bdpsy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int irq, i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static const struct irq_name_pair bd70528_chg_irqs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { .n = "bd70528-bat-ov-res", .h = BD_IRQ_HND(BAT_OV_RES) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { .n = "bd70528-bat-ov-det", .h = BD_IRQ_HND(BAT_OV_DET) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { .n = "bd70528-bat-dead", .h = BD_IRQ_HND(DBAT_DET) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) { .n = "bd70528-bat-warmed", .h = BD_IRQ_HND(COLD_RES) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) { .n = "bd70528-bat-cold", .h = BD_IRQ_HND(COLD_DET) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { .n = "bd70528-bat-cooled", .h = BD_IRQ_HND(HOT_RES) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) { .n = "bd70528-bat-hot", .h = BD_IRQ_HND(HOT_DET) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) { .n = "bd70528-chg-tshd", .h = BD_IRQ_HND(CHG_TSD) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { .n = "bd70528-bat-removed", .h = BD_IRQ_HND(BAT_RMV) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) { .n = "bd70528-bat-detected", .h = BD_IRQ_HND(BAT_DET) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) { .n = "bd70528-dcin2-ov-res", .h = BD_IRQ_HND(DCIN2_OV_RES) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) { .n = "bd70528-dcin2-ov-det", .h = BD_IRQ_HND(DCIN2_OV_DET) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) { .n = "bd70528-dcin2-removed", .h = BD_IRQ_HND(DCIN2_RMV) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { .n = "bd70528-dcin2-detected", .h = BD_IRQ_HND(DCIN2_DET) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) { .n = "bd70528-dcin1-removed", .h = BD_IRQ_HND(DCIN1_RMV) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) { .n = "bd70528-dcin1-detected", .h = BD_IRQ_HND(DCIN1_DET) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) for (i = 0; i < ARRAY_SIZE(bd70528_chg_irqs); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) irq = platform_get_irq_byname(pdev, bd70528_chg_irqs[i].n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) dev_err(&pdev->dev, "Bad IRQ information for %s (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) bd70528_chg_irqs[i].n, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) bd70528_chg_irqs[i].h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) bd70528_chg_irqs[i].n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) bdpsy->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * BD70528 irq controller is not touching the main mask register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * So enable the charger block interrupts at main level. We can just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * leave them enabled as irq-controller should disable irqs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * from sub-registers when IRQ is disabled or freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) mask = BD70528_REG_INT_BAT1_MASK | BD70528_REG_INT_BAT2_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ret = regmap_update_bits(bdpsy->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) BD70528_REG_INT_MAIN_MASK, mask, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dev_err(&pdev->dev, "Failed to enable charger IRQs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static int bd70528_get_charger_status(struct bd70528_psy *bdpsy, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned int v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CURR_STAT, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) dev_err(bdpsy->dev, "Charger state read failure %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) switch (v & BD70528_MASK_CHG_STAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) case CHG_STAT_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* Maybe we should check the CHG_TTRI_EN? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) case CHG_STAT_OTP_TRICKLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) case CHG_STAT_OTP_FAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) case CHG_STAT_OTP_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case CHG_STAT_TSD_TRICKLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) case CHG_STAT_TSD_FAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) case CHG_STAT_TSD_TOPOFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) case CHG_STAT_BAT_ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) case CHG_STAT_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *val = POWER_SUPPLY_STATUS_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) case CHG_STAT_TRICKLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) case CHG_STAT_FAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) case CHG_STAT_TOPOFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *val = POWER_SUPPLY_STATUS_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) *val = POWER_SUPPLY_STATUS_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static int bd70528_get_charge_type(struct bd70528_psy *bdpsy, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned int v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CURR_STAT, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) dev_err(bdpsy->dev, "Charger state read failure %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) switch (v & BD70528_MASK_CHG_STAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case CHG_STAT_TRICKLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case CHG_STAT_FAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case CHG_STAT_TOPOFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case CHG_STAT_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) case CHG_STAT_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* Maybe we should check the CHG_TTRI_EN? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) case CHG_STAT_OTP_TRICKLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) case CHG_STAT_OTP_FAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) case CHG_STAT_OTP_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case CHG_STAT_TSD_TRICKLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case CHG_STAT_TSD_FAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case CHG_STAT_TSD_TOPOFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) case CHG_STAT_BAT_ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int bd70528_get_battery_health(struct bd70528_psy *bdpsy, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) unsigned int v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_BAT_STAT, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) dev_err(bdpsy->dev, "Battery state read failure %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* No battery? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (!(v & BD70528_MASK_CHG_BAT_DETECT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) *val = POWER_SUPPLY_HEALTH_DEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) else if (v & BD70528_MASK_CHG_BAT_OVERVOLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) else if (v & BD70528_MASK_CHG_BAT_TIMER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) *val = POWER_SUPPLY_HEALTH_GOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int bd70528_get_online(struct bd70528_psy *bdpsy, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) unsigned int v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_IN_STAT, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dev_err(bdpsy->dev, "DC1 IN state read failure %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) *val = (v & BD70528_MASK_CHG_DCIN1_UVLO) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static int bd70528_get_present(struct bd70528_psy *bdpsy, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) unsigned int v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_BAT_STAT, &v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) dev_err(bdpsy->dev, "Battery state read failure %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) *val = (v & BD70528_MASK_CHG_BAT_DETECT) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static const struct linear_range current_limit_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .min = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .min_sel = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .max_sel = 0x22,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) .min = 40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) .step = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) .min_sel = 0x23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) .max_sel = 0x26,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .min = 60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .step = 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) .min_sel = 0x27,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .max_sel = 0x2d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) .min = 200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) .step = 50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) .min_sel = 0x2e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) .max_sel = 0x34,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) .min = 500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) .step = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) .min_sel = 0x35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) .max_sel = 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * BD70528 would support setting and getting own charge current/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * voltage for low temperatures. The driver currently only reads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * the charge current at room temperature. We do set both though.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static const struct linear_range warm_charge_curr[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .min = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .step = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .min_sel = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .max_sel = 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) .min = 200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .step = 25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .min_sel = 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .max_sel = 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * Cold charge current selectors are identical to warm charge current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * selectors. The difference is that only smaller currents are available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * at cold charge range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) #define MAX_COLD_CHG_CURR_SEL 0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) #define MAX_WARM_CHG_CURR_SEL 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) #define MIN_CHG_CURR_SEL 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static int get_charge_current(struct bd70528_psy *bdpsy, int *ma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) unsigned int sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CHG_CURR_WARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) &sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) dev_err(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) "Charge current reading failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) sel &= BD70528_MASK_CHG_CHG_CURR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ret = linear_range_get_value_array(&warm_charge_curr[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ARRAY_SIZE(warm_charge_curr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) sel, ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) dev_err(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) "Unknown charge current value 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static int get_current_limit(struct bd70528_psy *bdpsy, int *ma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) unsigned int sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_DCIN_ILIM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) &sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) dev_err(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) "Input current limit reading failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) sel &= BD70528_MASK_CHG_DCIN_ILIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ret = linear_range_get_value_array(¤t_limit_ranges[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ARRAY_SIZE(current_limit_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) sel, ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* Unspecified values mean 500 mA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) *ma = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static enum power_supply_property bd70528_charger_props[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) POWER_SUPPLY_PROP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) POWER_SUPPLY_PROP_CHARGE_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) POWER_SUPPLY_PROP_HEALTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) POWER_SUPPLY_PROP_PRESENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) POWER_SUPPLY_PROP_ONLINE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) POWER_SUPPLY_PROP_MODEL_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) POWER_SUPPLY_PROP_MANUFACTURER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static int bd70528_charger_get_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct bd70528_psy *bdpsy = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) case POWER_SUPPLY_PROP_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return bd70528_get_charger_status(bdpsy, &val->intval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) case POWER_SUPPLY_PROP_CHARGE_TYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return bd70528_get_charge_type(bdpsy, &val->intval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case POWER_SUPPLY_PROP_HEALTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return bd70528_get_battery_health(bdpsy, &val->intval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) case POWER_SUPPLY_PROP_PRESENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return bd70528_get_present(bdpsy, &val->intval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ret = get_current_limit(bdpsy, &val->intval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) val->intval *= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret = get_charge_current(bdpsy, &val->intval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) val->intval *= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) case POWER_SUPPLY_PROP_ONLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return bd70528_get_online(bdpsy, &val->intval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) case POWER_SUPPLY_PROP_MODEL_NAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) val->strval = bd70528_charger_model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) case POWER_SUPPLY_PROP_MANUFACTURER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) val->strval = bd70528_charger_manufacturer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static int bd70528_prop_is_writable(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) enum power_supply_property psp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static int set_charge_current(struct bd70528_psy *bdpsy, int ma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) int ret = 0, tmpret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) bool found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (ma > 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) dev_warn(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) "Requested charge current %u exceed maximum (500mA)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) reg = MAX_WARM_CHG_CURR_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) goto set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (ma < 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) dev_err(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) "Requested charge current %u smaller than min (10mA)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) reg = MIN_CHG_CURR_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) goto set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * For BD70528 voltage/current limits we happily accept any value which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * belongs the range. We could check if value matching the selector is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * desired by computing the range min + (sel - sel_low) * range step - but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * I guess it is enough if we use voltage/current which is closest (below)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * the requested?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ret = linear_range_get_selector_low_array(warm_charge_curr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) ARRAY_SIZE(warm_charge_curr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) ma, ®, &found);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) dev_err(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) "Unsupported charge current %u mA\n", ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) reg = MIN_CHG_CURR_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) goto set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * There was a gap in supported values and we hit it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * Yet a smaller value was found so we use it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) dev_warn(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) "Unsupported charge current %u mA\n", ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) set:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) tmpret = regmap_update_bits(bdpsy->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) BD70528_REG_CHG_CHG_CURR_WARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) BD70528_MASK_CHG_CHG_CURR, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (tmpret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) dev_err(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) "Charge current write failure (%d)\n", tmpret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (reg > MAX_COLD_CHG_CURR_SEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) reg = MAX_COLD_CHG_CURR_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (!tmpret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) tmpret = regmap_update_bits(bdpsy->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) BD70528_REG_CHG_CHG_CURR_COLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) BD70528_MASK_CHG_CHG_CURR, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) ret = tmpret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) #define MAX_CURR_LIMIT_SEL 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) #define MIN_CURR_LIMIT_SEL 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static int set_current_limit(struct bd70528_psy *bdpsy, int ma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) int ret = 0, tmpret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) bool found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (ma > 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) dev_warn(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) "Requested current limit %u exceed maximum (500mA)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) reg = MAX_CURR_LIMIT_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) goto set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (ma < 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) dev_err(bdpsy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) "Requested current limit %u smaller than min (5mA)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) reg = MIN_CURR_LIMIT_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) goto set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) ret = linear_range_get_selector_low_array(current_limit_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) ARRAY_SIZE(current_limit_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) ma, ®, &found);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) dev_err(bdpsy->dev, "Unsupported current limit %umA\n", ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) reg = MIN_CURR_LIMIT_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) goto set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * There was a gap in supported values and we hit it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * We found a smaller value from ranges and use it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * Warn user though.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) dev_warn(bdpsy->dev, "Unsupported current limit %umA\n", ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) set:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) tmpret = regmap_update_bits(bdpsy->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) BD70528_REG_CHG_DCIN_ILIM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) BD70528_MASK_CHG_DCIN_ILIM, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ret = tmpret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static int bd70528_charger_set_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) const union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct bd70528_psy *bdpsy = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return set_current_limit(bdpsy, val->intval / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return set_charge_current(bdpsy, val->intval / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) static const struct power_supply_desc bd70528_charger_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) .name = "bd70528-charger",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) .type = POWER_SUPPLY_TYPE_MAINS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) .properties = bd70528_charger_props,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) .num_properties = ARRAY_SIZE(bd70528_charger_props),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) .get_property = bd70528_charger_get_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) .set_property = bd70528_charger_set_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) .property_is_writeable = bd70528_prop_is_writable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static int bd70528_power_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct bd70528_psy *bdpsy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct power_supply_config cfg = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) bdpsy = devm_kzalloc(&pdev->dev, sizeof(*bdpsy), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (!bdpsy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) bdpsy->regmap = dev_get_regmap(pdev->dev.parent, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (!bdpsy->regmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) dev_err(&pdev->dev, "No regmap found for chip\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) bdpsy->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) platform_set_drvdata(pdev, bdpsy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) cfg.drv_data = bdpsy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) cfg.of_node = pdev->dev.parent->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) bdpsy->psy = devm_power_supply_register(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) &bd70528_charger_desc, &cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (IS_ERR(bdpsy->psy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) dev_err(&pdev->dev, "failed: power supply register\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return PTR_ERR(bdpsy->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return bd70528_get_irqs(pdev, bdpsy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static struct platform_driver bd70528_power = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .name = "bd70528-power"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) .probe = bd70528_power_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) module_platform_driver(bd70528_power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) MODULE_DESCRIPTION("BD70528 power-supply driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) MODULE_ALIAS("platform:bd70528-power");