^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) * TWL4030/TPS65950 BCI (Battery Charger Interface) driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010 Gražvydas Ignotas <notasas@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * based on twl4030_bci_battery.c by TI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2008 Texas Instruments, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mfd/twl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/power_supply.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/usb/otg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/iio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define TWL4030_BCIMDEN 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define TWL4030_BCIMDKEY 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define TWL4030_BCIMSTATEC 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define TWL4030_BCIICHG 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define TWL4030_BCIVAC 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define TWL4030_BCIVBUS 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define TWL4030_BCIMFSTS3 0x0F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define TWL4030_BCIMFSTS4 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define TWL4030_BCICTL1 0x23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define TWL4030_BB_CFG 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define TWL4030_BCIIREF1 0x27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define TWL4030_BCIIREF2 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define TWL4030_BCIMFKEY 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define TWL4030_BCIMFEN3 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define TWL4030_BCIMFTH8 0x1d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define TWL4030_BCIMFTH9 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define TWL4030_BCIWDKEY 0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define TWL4030_BCIMFSTS1 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define TWL4030_BCIAUTOWEN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define TWL4030_CONFIG_DONE BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define TWL4030_CVENAC BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define TWL4030_BCIAUTOUSB BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define TWL4030_BCIAUTOAC BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define TWL4030_CGAIN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define TWL4030_USBFASTMCHG BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define TWL4030_STS_VBUS BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define TWL4030_STS_USB_ID BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define TWL4030_BBCHEN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define TWL4030_BBSEL_MASK 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define TWL4030_BBSEL_2V5 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define TWL4030_BBSEL_3V0 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define TWL4030_BBSEL_3V1 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define TWL4030_BBSEL_3V2 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define TWL4030_BBISEL_MASK 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define TWL4030_BBISEL_25uA 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define TWL4030_BBISEL_150uA 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define TWL4030_BBISEL_500uA 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define TWL4030_BBISEL_1000uA 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define TWL4030_BATSTSPCHG BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define TWL4030_BATSTSMCHG BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* BCI interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define TWL4030_WOVF BIT(0) /* Watchdog overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define TWL4030_TMOVF BIT(1) /* Timer overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define TWL4030_ICHGHIGH BIT(2) /* Battery charge current high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define TWL4030_ICHGLOW BIT(3) /* Battery cc. low / FSM state change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define TWL4030_ICHGEOC BIT(4) /* Battery current end-of-charge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define TWL4030_TBATOR2 BIT(5) /* Battery temperature out of range 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define TWL4030_TBATOR1 BIT(6) /* Battery temperature out of range 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define TWL4030_BATSTS BIT(7) /* Battery status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define TWL4030_VBATLVL BIT(0) /* VBAT level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define TWL4030_VBATOV BIT(1) /* VBAT overvoltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define TWL4030_VBUSOV BIT(2) /* VBUS overvoltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define TWL4030_ACCHGOV BIT(3) /* Ac charger overvoltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define TWL4030_MSTATEC_USB BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define TWL4030_MSTATEC_AC BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define TWL4030_MSTATEC_MASK 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define TWL4030_MSTATEC_QUICK1 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define TWL4030_MSTATEC_QUICK7 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define TWL4030_MSTATEC_COMPLETE1 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define TWL4030_MSTATEC_COMPLETE4 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * then AC is available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static inline int ac_available(struct iio_channel *channel_vac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int val, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (!channel_vac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) err = iio_read_channel_processed(channel_vac, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return val > 4500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static bool allow_usb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) module_param(allow_usb, bool, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct twl4030_bci {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct power_supply *ac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct power_supply *usb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct usb_phy *transceiver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct notifier_block usb_nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int irq_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int irq_bci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int usb_enabled;
^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) * ichg_* and *_cur values in uA. If any are 'large', we set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * CGAIN to '1' which doubles the range for half the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned int ichg_eoc, ichg_lo, ichg_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned int usb_cur, ac_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct iio_channel *channel_vac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) bool ac_is_active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int usb_mode, ac_mode; /* charging mode requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define CHARGE_OFF 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define CHARGE_AUTO 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define CHARGE_LINEAR 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* When setting the USB current we slowly increase the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * requested current until target is reached or the voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * drops below 4.75V. In the latter case we step back one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * step.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int usb_cur_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct delayed_work current_worker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define USB_CUR_STEP 20000 /* 20mA at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define USB_MIN_VOLT 4750000 /* 4.75V */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define USB_CUR_DELAY msecs_to_jiffies(100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define USB_MAX_CURRENT 1700000 /* TWL4030 caps at 1.7A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned long event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* strings for 'usb_mode' values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static const char *modes[] = { "off", "auto", "continuous" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * clear and set bits on an given register on a given module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int twl4030_clear_set(u8 mod_no, u8 clear, u8 set, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) u8 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ret = twl_i2c_read_u8(mod_no, &val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) val &= ~clear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) val |= set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return twl_i2c_write_u8(mod_no, val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static int twl4030_bci_read(u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static int twl4030_clear_set_boot_bci(u8 clear, u8 set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return twl4030_clear_set(TWL_MODULE_PM_MASTER, clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) TWL4030_PM_MASTER_BOOT_BCI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static int twl4030bci_read_adc_val(u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int ret, temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* read MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret = twl4030_bci_read(reg + 1, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) temp = (int)(val & 0x03) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* read LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ret = twl4030_bci_read(reg, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return temp | val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * TI provided formulas:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * Here we use integer approximation of:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * CGAIN == 0: val * 1.6618 - 0.85 * 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * CGAIN == 1: (val * 1.6618 - 0.85 * 1000) * 2
^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) * convert twl register value for currents into uA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int regval2ua(int regval, bool cgain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (cgain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return (regval * 16618 - 8500 * 1000) / 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return (regval * 16618 - 8500 * 1000) / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * convert uA currents into twl register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static int ua2regval(int ua, bool cgain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (cgain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ua /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) ret = (ua * 10 + 8500 * 1000) / 16618;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* rounding problems */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (ret < 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ret = 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return ret;
^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) static int twl4030_charger_update_current(struct twl4030_bci *bci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned reg, cur_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) u8 bcictl1, oldreg, fullreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) bool cgain = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) u8 boot_bci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * and AC is enabled, set current for 'ac'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (ac_available(bci->channel_vac)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) cur = bci->ac_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) bci->ac_is_active = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) cur = bci->usb_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) bci->ac_is_active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (cur > bci->usb_cur_target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) cur = bci->usb_cur_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) bci->usb_cur = cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (cur < bci->usb_cur_target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) schedule_delayed_work(&bci->current_worker, USB_CUR_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* First, check thresholds and see if cgain is needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (bci->ichg_eoc >= 200000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) cgain = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (bci->ichg_lo >= 400000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) cgain = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (bci->ichg_hi >= 820000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) cgain = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (cur > 852000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) cgain = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &boot_bci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) TWL4030_PM_MASTER_BOOT_BCI) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) boot_bci = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) boot_bci &= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if ((!!cgain) != !!(bcictl1 & TWL4030_CGAIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /* Need to turn for charging while we change the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * CGAIN bit. Leave it off while everything is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) twl4030_clear_set_boot_bci(boot_bci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * For ichg_eoc, the hardware only supports reg values matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * 100XXXX000, and requires the XXXX be stored in the high nibble
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * of TWL4030_BCIMFTH8.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) reg = ua2regval(bci->ichg_eoc, cgain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (reg > 0x278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) reg = 0x278;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (reg < 0x200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) reg = 0x200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) reg = (reg >> 3) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) fullreg = reg << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * For ichg_lo, reg value must match 10XXXX0000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * XXXX is stored in low nibble of TWL4030_BCIMFTH8.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) reg = ua2regval(bci->ichg_lo, cgain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (reg > 0x2F0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) reg = 0x2F0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (reg < 0x200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) reg = 0x200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) reg = (reg >> 4) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) fullreg |= reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* ichg_eoc and ichg_lo live in same register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) status = twl4030_bci_read(TWL4030_BCIMFTH8, &oldreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (oldreg != fullreg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xF4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) TWL4030_BCIMFKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) fullreg, TWL4030_BCIMFTH8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* ichg_hi threshold must be 1XXXX01100 (I think) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) reg = ua2regval(bci->ichg_hi, cgain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (reg > 0x3E0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) reg = 0x3E0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (reg < 0x200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) reg = 0x200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) fullreg = (reg >> 5) & 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) fullreg <<= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) status = twl4030_bci_read(TWL4030_BCIMFTH9, &oldreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if ((oldreg & 0xF0) != fullreg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) fullreg |= (oldreg & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) TWL4030_BCIMFKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) fullreg, TWL4030_BCIMFTH9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * And finally, set the current. This is stored in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * two registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) reg = ua2regval(cur, cgain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* we have only 10 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (reg > 0x3ff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) reg = 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) status = twl4030_bci_read(TWL4030_BCIIREF1, &oldreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) cur_reg = oldreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) status = twl4030_bci_read(TWL4030_BCIIREF2, &oldreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) cur_reg |= oldreg << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (reg != oldreg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* disable write protection for one write access for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * BCIIREF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) TWL4030_BCIMFKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) (reg & 0x100) ? 3 : 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) TWL4030_BCIIREF2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* disable write protection for one write access for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * BCIIREF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) TWL4030_BCIMFKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) reg & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) TWL4030_BCIIREF1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if ((!!cgain) != !!(bcictl1 & TWL4030_CGAIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* Flip CGAIN and re-enable charging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) bcictl1 ^= TWL4030_CGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) bcictl1, TWL4030_BCICTL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) twl4030_clear_set_boot_bci(0, boot_bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int twl4030_charger_get_current(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static void twl4030_current_worker(struct work_struct *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int v, curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct twl4030_bci *bci = container_of(data, struct twl4030_bci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) current_worker.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) res = twl4030bci_read_adc_val(TWL4030_BCIVBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) v = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* BCIVBUS uses ADCIN8, 7/1023 V/step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) v = res * 6843;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) curr = twl4030_charger_get_current();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dev_dbg(bci->dev, "v=%d cur=%d limit=%d target=%d\n", v, curr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) bci->usb_cur, bci->usb_cur_target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (v < USB_MIN_VOLT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* Back up and stop adjusting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (bci->usb_cur >= USB_CUR_STEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) bci->usb_cur -= USB_CUR_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) bci->usb_cur_target = bci->usb_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else if (bci->usb_cur >= bci->usb_cur_target ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) bci->usb_cur + USB_CUR_STEP > USB_MAX_CURRENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* Reached target and voltage is OK - stop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) bci->usb_cur += USB_CUR_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) schedule_delayed_work(&bci->current_worker, USB_CUR_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) twl4030_charger_update_current(bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * Enable/Disable USB Charge functionality.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (bci->usb_mode == CHARGE_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) twl4030_charger_update_current(bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /* Need to keep phy powered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!bci->usb_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) pm_runtime_get_sync(bci->transceiver->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) bci->usb_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (bci->usb_mode == CHARGE_AUTO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Enable interrupts now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) TWL4030_TBATOR2 | TWL4030_TBATOR1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) TWL4030_BATSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) TWL4030_INTERRUPTS_BCIIMR1A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) dev_err(bci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) "failed to unmask interrupts: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (bci->usb_mode == CHARGE_LINEAR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Enable interrupts now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_TBATOR2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) TWL4030_TBATOR1 | TWL4030_BATSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) TWL4030_INTERRUPTS_BCIIMR1A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) dev_err(bci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) "failed to unmask interrupts: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC|TWL4030_CVENAC, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* Watch dog key: WOVF acknowledge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) TWL4030_BCIWDKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* 0x24 + EKEY6: off mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) TWL4030_BCIMDKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* EKEY2: Linear charge: USB path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x26,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) TWL4030_BCIMDKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* WDKEY5: stop watchdog count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) TWL4030_BCIWDKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* enable MFEN3 access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x9c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) TWL4030_BCIMFKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* ICHGEOCEN - end-of-charge monitor (current < 80mA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * (charging continues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * ICHGLOWEN - current level monitor (charge continues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * don't monitor over-current or heat save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) TWL4030_BCIMFEN3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) ret |= twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) TWL4030_BCIMDKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (bci->usb_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) pm_runtime_mark_last_busy(bci->transceiver->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) pm_runtime_put_autosuspend(bci->transceiver->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) bci->usb_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) bci->usb_cur = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * Enable/Disable AC Charge funtionality.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static int twl4030_charger_enable_ac(struct twl4030_bci *bci, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (bci->ac_mode == CHARGE_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * Enable/Disable charging of Backup Battery.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static int twl4030_charger_enable_backup(int uvolt, int uamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) u8 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (uvolt < 2500000 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) uamp < 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /* disable charging of backup battery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) TWL4030_BBCHEN, 0, TWL4030_BB_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) flags = TWL4030_BBCHEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (uvolt >= 3200000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) flags |= TWL4030_BBSEL_3V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) else if (uvolt >= 3100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) flags |= TWL4030_BBSEL_3V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) else if (uvolt >= 3000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) flags |= TWL4030_BBSEL_3V0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) flags |= TWL4030_BBSEL_2V5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (uamp >= 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) flags |= TWL4030_BBISEL_1000uA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) else if (uamp >= 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) flags |= TWL4030_BBISEL_500uA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) else if (uamp >= 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) flags |= TWL4030_BBISEL_150uA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) flags |= TWL4030_BBISEL_25uA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) TWL4030_BBSEL_MASK | TWL4030_BBISEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) TWL4030_BB_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * TWL4030 CHG_PRES (AC charger presence) events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static irqreturn_t twl4030_charger_interrupt(int irq, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct twl4030_bci *bci = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) dev_dbg(bci->dev, "CHG_PRES irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) /* reset current on each 'plug' event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) bci->ac_cur = 500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) twl4030_charger_update_current(bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) power_supply_changed(bci->ac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) power_supply_changed(bci->usb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * TWL4030 BCI monitoring events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct twl4030_bci *bci = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) u8 irqs1, irqs2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ret = twl_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &irqs1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) TWL4030_INTERRUPTS_BCIISR1A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ret = twl_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &irqs2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) TWL4030_INTERRUPTS_BCIISR2A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) dev_dbg(bci->dev, "BCI irq %02x %02x\n", irqs2, irqs1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (irqs1 & (TWL4030_ICHGLOW | TWL4030_ICHGEOC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) /* charger state change, inform the core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) power_supply_changed(bci->ac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) power_supply_changed(bci->usb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) twl4030_charger_update_current(bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* various monitoring events, for now we just log them here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) dev_warn(bci->dev, "battery temperature out of range\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (irqs1 & TWL4030_BATSTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) dev_crit(bci->dev, "battery disconnected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (irqs2 & TWL4030_VBATOV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) dev_crit(bci->dev, "VBAT overvoltage\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (irqs2 & TWL4030_VBUSOV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) dev_crit(bci->dev, "VBUS overvoltage\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (irqs2 & TWL4030_ACCHGOV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) dev_crit(bci->dev, "Ac charger overvoltage\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static void twl4030_bci_usb_work(struct work_struct *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) switch (bci->event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) case USB_EVENT_VBUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) case USB_EVENT_CHARGER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) twl4030_charger_enable_usb(bci, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) case USB_EVENT_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) twl4030_charger_enable_usb(bci, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, usb_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) dev_dbg(bci->dev, "OTG notify %lu\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /* reset current on each 'plug' event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (allow_usb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) bci->usb_cur_target = 500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) bci->usb_cur_target = 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) bci->event = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) schedule_work(&bci->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * sysfs charger enabled store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) const char *buf, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) mode = sysfs_match_string(modes, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (mode < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (dev == &bci->ac->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (mode == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) twl4030_charger_enable_ac(bci, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) bci->ac_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) status = twl4030_charger_enable_ac(bci, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) twl4030_charger_enable_usb(bci, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) bci->usb_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) status = twl4030_charger_enable_usb(bci, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return (status == 0) ? n : status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * sysfs charger enabled show
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) twl4030_bci_mode_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) int mode = bci->usb_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (dev == &bci->ac->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) mode = bci->ac_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) for (i = 0; i < ARRAY_SIZE(modes); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (mode == i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) len += scnprintf(buf+len, PAGE_SIZE-len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) "[%s] ", modes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) len += scnprintf(buf+len, PAGE_SIZE-len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) "%s ", modes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) buf[len-1] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) static DEVICE_ATTR(mode, 0644, twl4030_bci_mode_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) twl4030_bci_mode_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static int twl4030_charger_get_current(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) int curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) u8 bcictl1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) curr = twl4030bci_read_adc_val(TWL4030_BCIICHG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (curr < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ret = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return regval2ua(curr, bcictl1 & TWL4030_CGAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * Returns the main charge FSM state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * Or < 0 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static int twl4030bci_state(struct twl4030_bci *bci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) u8 state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) ret = twl4030_bci_read(TWL4030_BCIMSTATEC, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) dev_err(bci->dev, "error reading BCIMSTATEC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) dev_dbg(bci->dev, "state: %02x\n", state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) static int twl4030_bci_state_to_status(int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) state &= TWL4030_MSTATEC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (TWL4030_MSTATEC_QUICK1 <= state && state <= TWL4030_MSTATEC_QUICK7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return POWER_SUPPLY_STATUS_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) else if (TWL4030_MSTATEC_COMPLETE1 <= state &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) state <= TWL4030_MSTATEC_COMPLETE4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return POWER_SUPPLY_STATUS_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return POWER_SUPPLY_STATUS_NOT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static int twl4030_bci_get_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) struct twl4030_bci *bci = dev_get_drvdata(psy->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) int is_charging;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) state = twl4030bci_state(bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (state < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (psy->desc->type == POWER_SUPPLY_TYPE_USB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) is_charging = state & TWL4030_MSTATEC_USB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) is_charging = state & TWL4030_MSTATEC_AC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (!is_charging) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) u8 s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) ret = twl4030_bci_read(TWL4030_BCIMDEN, &s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (psy->desc->type == POWER_SUPPLY_TYPE_USB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) is_charging = s & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) is_charging = s & 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (is_charging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* A little white lie */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) state = TWL4030_MSTATEC_QUICK1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) case POWER_SUPPLY_PROP_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (is_charging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) val->intval = twl4030_bci_state_to_status(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) case POWER_SUPPLY_PROP_VOLTAGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /* charging must be active for meaningful result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (!is_charging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (psy->desc->type == POWER_SUPPLY_TYPE_USB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) ret = twl4030bci_read_adc_val(TWL4030_BCIVBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* BCIVBUS uses ADCIN8, 7/1023 V/step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) val->intval = ret * 6843;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) ret = twl4030bci_read_adc_val(TWL4030_BCIVAC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* BCIVAC uses ADCIN11, 10/1023 V/step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) val->intval = ret * 9775;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) case POWER_SUPPLY_PROP_CURRENT_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (!is_charging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /* current measurement is shared between AC and USB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) ret = twl4030_charger_get_current();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) val->intval = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) case POWER_SUPPLY_PROP_ONLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) val->intval = is_charging &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) twl4030_bci_state_to_status(state) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) POWER_SUPPLY_STATUS_NOT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) val->intval = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (psy->desc->type != POWER_SUPPLY_TYPE_USB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (!bci->ac_is_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) val->intval = bci->ac_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (bci->ac_is_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) val->intval = bci->usb_cur_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (val->intval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) u8 bcictl1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) val->intval = twl4030bci_read_adc_val(TWL4030_BCIIREF1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (val->intval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return val->intval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ret = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) val->intval = regval2ua(val->intval, bcictl1 &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) TWL4030_CGAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) static int twl4030_bci_set_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) const union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct twl4030_bci *bci = dev_get_drvdata(psy->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (psy->desc->type == POWER_SUPPLY_TYPE_USB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) bci->usb_cur_target = val->intval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) bci->ac_cur = val->intval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) twl4030_charger_update_current(bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static int twl4030_bci_property_is_writeable(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) enum power_supply_property psp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static enum power_supply_property twl4030_charger_props[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) POWER_SUPPLY_PROP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) POWER_SUPPLY_PROP_ONLINE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) POWER_SUPPLY_PROP_VOLTAGE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) POWER_SUPPLY_PROP_CURRENT_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) static const struct twl4030_bci_platform_data *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) twl4030_bci_parse_dt(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct twl4030_bci_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) u32 num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (of_property_read_u32(np, "ti,bb-uvolt", &num) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) pdata->bb_uvolt = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (of_property_read_u32(np, "ti,bb-uamp", &num) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) pdata->bb_uamp = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static inline const struct twl4030_bci_platform_data *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) twl4030_bci_parse_dt(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static const struct power_supply_desc twl4030_bci_ac_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) .name = "twl4030_ac",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) .type = POWER_SUPPLY_TYPE_MAINS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) .properties = twl4030_charger_props,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) .num_properties = ARRAY_SIZE(twl4030_charger_props),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) .get_property = twl4030_bci_get_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) .set_property = twl4030_bci_set_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) .property_is_writeable = twl4030_bci_property_is_writeable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) static const struct power_supply_desc twl4030_bci_usb_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) .name = "twl4030_usb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) .type = POWER_SUPPLY_TYPE_USB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .properties = twl4030_charger_props,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .num_properties = ARRAY_SIZE(twl4030_charger_props),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .get_property = twl4030_bci_get_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .set_property = twl4030_bci_set_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) .property_is_writeable = twl4030_bci_property_is_writeable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) static int twl4030_bci_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct twl4030_bci *bci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) const struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) bci = devm_kzalloc(&pdev->dev, sizeof(*bci), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (bci == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) pdata = twl4030_bci_parse_dt(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) bci->ichg_eoc = 80100; /* Stop charging when current drops to here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) bci->ichg_lo = 241000; /* Low threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) bci->ichg_hi = 500000; /* High threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) bci->ac_cur = 500000; /* 500mA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (allow_usb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) bci->usb_cur_target = 500000; /* 500mA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) bci->usb_cur_target = 100000; /* 100mA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) bci->usb_mode = CHARGE_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) bci->ac_mode = CHARGE_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) bci->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) bci->irq_chg = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) bci->irq_bci = platform_get_irq(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) platform_set_drvdata(pdev, bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) INIT_WORK(&bci->work, twl4030_bci_usb_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) INIT_DELAYED_WORK(&bci->current_worker, twl4030_current_worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) bci->channel_vac = devm_iio_channel_get(&pdev->dev, "vac");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (IS_ERR(bci->channel_vac)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) ret = PTR_ERR(bci->channel_vac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return ret; /* iio not ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) dev_warn(&pdev->dev, "could not request vac iio channel (%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) bci->channel_vac = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (bci->dev->of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) struct device_node *phynode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) phynode = of_get_compatible_child(bci->dev->of_node->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) "ti,twl4030-usb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (phynode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) bci->transceiver = devm_usb_get_phy_by_node(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) bci->dev, phynode, &bci->usb_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) of_node_put(phynode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (IS_ERR(bci->transceiver)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) ret = PTR_ERR(bci->transceiver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return ret; /* phy not ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) dev_warn(&pdev->dev, "could not request transceiver (%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) bci->transceiver = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) bci->ac = devm_power_supply_register(&pdev->dev, &twl4030_bci_ac_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (IS_ERR(bci->ac)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) ret = PTR_ERR(bci->ac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) bci->usb = devm_power_supply_register(&pdev->dev, &twl4030_bci_usb_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (IS_ERR(bci->usb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) ret = PTR_ERR(bci->usb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) ret = devm_request_threaded_irq(&pdev->dev, bci->irq_chg, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) twl4030_charger_interrupt, IRQF_ONESHOT, pdev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) dev_err(&pdev->dev, "could not request irq %d, status %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) bci->irq_chg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) ret = devm_request_threaded_irq(&pdev->dev, bci->irq_bci, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) twl4030_bci_interrupt, IRQF_ONESHOT, pdev->name, bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) dev_err(&pdev->dev, "could not request irq %d, status %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) bci->irq_bci, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* Enable interrupts now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) TWL4030_TBATOR1 | TWL4030_BATSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) TWL4030_INTERRUPTS_BCIIMR1A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) TWL4030_INTERRUPTS_BCIIMR2A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) twl4030_charger_update_current(bci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (device_create_file(&bci->usb->dev, &dev_attr_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) dev_warn(&pdev->dev, "could not create sysfs file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (device_create_file(&bci->ac->dev, &dev_attr_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) dev_warn(&pdev->dev, "could not create sysfs file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) twl4030_charger_enable_ac(bci, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (!IS_ERR_OR_NULL(bci->transceiver))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) twl4030_bci_usb_ncb(&bci->usb_nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) bci->transceiver->last_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) twl4030_charger_enable_usb(bci, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) twl4030_charger_enable_backup(pdata->bb_uvolt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) pdata->bb_uamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) twl4030_charger_enable_backup(0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) static int twl4030_bci_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) struct twl4030_bci *bci = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) twl4030_charger_enable_ac(bci, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) twl4030_charger_enable_usb(bci, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) twl4030_charger_enable_backup(0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) device_remove_file(&bci->usb->dev, &dev_attr_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) device_remove_file(&bci->ac->dev, &dev_attr_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /* mask interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) TWL4030_INTERRUPTS_BCIIMR1A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) TWL4030_INTERRUPTS_BCIIMR2A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static const struct of_device_id twl_bci_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) {.compatible = "ti,twl4030-bci", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) MODULE_DEVICE_TABLE(of, twl_bci_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static struct platform_driver twl4030_bci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) .probe = twl4030_bci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) .remove = twl4030_bci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) .name = "twl4030_bci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) .of_match_table = of_match_ptr(twl_bci_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) module_platform_driver(twl4030_bci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) MODULE_AUTHOR("Gražvydas Ignotas");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) MODULE_DESCRIPTION("TWL4030 Battery Charger Interface driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) MODULE_ALIAS("platform:twl4030_bci");