Loading arch/arm/boot/dts/qcom/msm-pm660.dtsi +74 −0 Original line number Diff line number Diff line Loading @@ -302,6 +302,7 @@ }; pm660_charger: qcom,qpnp-smb2 { spmi-dev-container; compatible = "qcom,qpnp-smb2"; #address-cells = <1>; #size-cells = <1>; Loading Loading @@ -424,6 +425,79 @@ }; }; pm660_rradc: rradc@4500 { compatible = "qcom,rradc"; reg = <0x4500 0x100>; #address-cells = <1>; #size-cells = <0>; #io-channel-cells = <1>; qcom,pmic-revid = <&pm660_revid>; }; pm660_fg: qpnp,fg { spmi-dev-container; compatible = "qcom,fg-gen3"; #address-cells = <1>; #size-cells = <1>; qcom,pmic-revid = <&pm660_revid>; io-channels = <&pm660_rradc 0>, <&pm660_rradc 7>; io-channel-names = "rradc_batt_id", "rradc_die_temp"; qcom,rradc-base = <0x4500>; qcom,fg-esr-timer-awake = <96 96>; qcom,fg-esr-timer-asleep = <256 256>; qcom,fg-esr-timer-charging = <0 96>; qcom,cycle-counter-en; status = "okay"; qcom,fg-batt-soc@4000 { status = "okay"; reg = <0x4000 0x100>; interrupts = <0x0 0x40 0x0>, <0x0 0x40 0x1>, <0x0 0x40 0x2>, <0x0 0x40 0x3>, <0x0 0x40 0x4>, <0x0 0x40 0x5>, <0x0 0x40 0x6>, <0x0 0x40 0x7>; interrupt-names = "soc-update", "soc-ready", "bsoc-delta", "msoc-delta", "msoc-low", "msoc-empty", "msoc-high", "msoc-full"; }; qcom,fg-batt-info@4100 { status = "okay"; reg = <0x4100 0x100>; interrupts = <0x0 0x41 0x0>, <0x0 0x41 0x1>, <0x0 0x41 0x2>, <0x0 0x41 0x3>, <0x0 0x41 0x6>; interrupt-names = "vbatt-pred-delta", "vbatt-low", "esr-delta", "batt-missing", "batt-temp-delta"; }; qcom,fg-memif@4400 { status = "okay"; reg = <0x4400 0x100>; interrupts = <0x0 0x44 0x0>, <0x0 0x44 0x1>, <0x0 0x44 0x2>; interrupt-names = "ima-rdy", "mem-xcp", "dma-grant"; }; }; pm660_pbs: qcom,pbs@7300 { compatible = "qcom,qpnp-pbs"; Loading drivers/iio/adc/qcom-rradc.c +116 −43 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/regmap.h> #include <linux/delay.h> #include <linux/qpnp/qpnp-revid.h> #include <linux/spmi.h> #define FG_ADC_RR_EN_CTL 0x46 #define FG_ADC_RR_SKIN_TEMP_LSB 0x50 Loading Loading @@ -223,6 +224,9 @@ struct rradc_chip { struct mutex lock; struct regmap *regmap; u16 base; struct spmi_device *spmi; u8 slave; u16 offset; struct iio_chan_spec *iio_chans; unsigned int nchannels; struct rradc_chan_prop *chan_props; Loading @@ -248,21 +252,36 @@ struct rradc_chan_prop { u16 adc_code, int *result); }; static int rradc_masked_write(struct rradc_chip *rr_adc, u16 offset, u8 mask, u8 val) static int rradc_spmi_read(struct rradc_chip *rr_adc, unsigned int reg, u8 *data, int len) { int rc; rc = regmap_update_bits(rr_adc->regmap, rr_adc->base + offset, mask, val); if (rc) { pr_err("spmi write failed: addr=%03X, rc=%d\n", offset, rc); rc = spmi_ext_register_readl(rr_adc->spmi->ctrl, rr_adc->slave, reg, data, len); if (rc < 0) { pr_err("rradc spmi read reg %x failed with %d\n", reg, rc); return rc; } return 0; } static int rradc_spmi_write(struct rradc_chip *rr_adc, u16 reg, u8 *buf, int len) { int rc; rc = spmi_ext_register_writel(rr_adc->spmi->ctrl, rr_adc->slave, reg, buf, len); if (rc < 0) { pr_err("rradc spmi write reg %d failed with %d\n", reg, rc); return rc; } return 0; } static int rradc_read(struct rradc_chip *rr_adc, u16 offset, u8 *data, int len) { int rc = 0, retry_cnt = 0, i = 0; Loading @@ -275,14 +294,14 @@ static int rradc_read(struct rradc_chip *rr_adc, u16 offset, u8 *data, int len) } while (retry_cnt < FG_RR_ADC_COHERENT_CHECK_RETRY) { rc = regmap_bulk_read(rr_adc->regmap, rr_adc->base + offset, rc = rradc_spmi_read(rr_adc, rr_adc->base + offset, data, len); if (rc < 0) { pr_err("rr_adc reg 0x%x failed :%d\n", offset, rc); return rc; } rc = regmap_bulk_read(rr_adc->regmap, rr_adc->base + offset, rc = rradc_spmi_read(rr_adc, rr_adc->base + offset, data_check, len); if (rc < 0) { pr_err("rr_adc reg 0x%x failed :%d\n", offset, rc); Loading Loading @@ -635,27 +654,35 @@ static const struct rradc_channels rradc_chans[] = { static int rradc_enable_continuous_mode(struct rradc_chip *chip) { int rc = 0; u8 result, value; /* Clear channel log */ rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG, FG_ADC_RR_ADC_LOG_CLR_CTRL, FG_ADC_RR_ADC_LOG_CLR_CTRL); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_ADC_LOG, &result, 1); value = (result) | FG_ADC_RR_ADC_LOG_CLR_CTRL; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_ADC_LOG, &value, 1); if (rc < 0) { pr_err("log ctrl update to clear failed:%d\n", rc); return rc; } rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG, FG_ADC_RR_ADC_LOG_CLR_CTRL, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_ADC_LOG, &result, 1); value = (result) & ~(FG_ADC_RR_ADC_LOG_CLR_CTRL); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_ADC_LOG, &value, 1); if (rc < 0) { pr_err("log ctrl update to not clear failed:%d\n", rc); return rc; } /* Switch to continuous mode */ rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL, FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK, FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_RR_ADC_CTL, &result, 1); value = (result) | FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_RR_ADC_CTL, &value, 1); if (rc < 0) { pr_err("Update to continuous mode failed:%d\n", rc); return rc; Loading @@ -667,10 +694,14 @@ static int rradc_enable_continuous_mode(struct rradc_chip *chip) static int rradc_disable_continuous_mode(struct rradc_chip *chip) { int rc = 0; u8 result, value; /* Switch to non continuous mode */ rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL, FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_RR_ADC_CTL, &result, 1); value = (result) & ~(FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_RR_ADC_CTL, &value, 1); if (rc < 0) { pr_err("Update to non-continuous mode failed:%d\n", rc); return rc; Loading Loading @@ -752,18 +783,24 @@ static int rradc_read_channel_with_continuous_mode(struct rradc_chip *chip, static int rradc_enable_batt_id_channel(struct rradc_chip *chip, bool enable) { int rc = 0; u8 result, value; if (enable) { rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_CTRL, FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV, FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL, &result, 1); value = (result) | FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL, &value, 1); if (rc < 0) { pr_err("Enabling BATT ID channel failed:%d\n", rc); return rc; } } else { rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_CTRL, FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL, &result, 1); value = (result) & ~(FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL, &value, 1); if (rc < 0) { pr_err("Disabling BATT ID channel failed:%d\n", rc); return rc; Loading @@ -777,6 +814,7 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip, struct rradc_chan_prop *prop, u16 *data, u8 *buf) { int rc = 0, ret = 0; u8 result, value; rc = rradc_enable_batt_id_channel(chip, true); if (rc < 0) { Loading @@ -784,9 +822,11 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip, return rc; } rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_TRIGGER, FG_ADC_RR_BATT_ID_TRIGGER_CTL, FG_ADC_RR_BATT_ID_TRIGGER_CTL); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER, &result, 1); value = (result) | FG_ADC_RR_BATT_ID_TRIGGER_CTL; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER, &value, 1); if (rc < 0) { pr_err("BATT_ID trigger set failed:%d\n", rc); ret = rc; Loading @@ -802,8 +842,11 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip, ret = rc; } rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_TRIGGER, FG_ADC_RR_BATT_ID_TRIGGER_CTL, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER, &result, 1); value = (result) & ~(FG_ADC_RR_BATT_ID_TRIGGER_CTL); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER, &value, 1); if (rc < 0) { pr_err("BATT_ID trigger re-set failed:%d\n", rc); ret = rc; Loading @@ -825,6 +868,7 @@ static int rradc_do_conversion(struct rradc_chip *chip, u8 buf[6]; u16 offset = 0, batt_id_5 = 0, batt_id_15 = 0, batt_id_150 = 0; u16 status = 0; u8 result, value; mutex_lock(&chip->lock); Loading @@ -838,9 +882,13 @@ static int rradc_do_conversion(struct rradc_chip *chip, break; case RR_ADC_USBIN_V: /* Force conversion every cycle */ rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER, FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK, FG_ADC_RR_USB_IN_V_EVERY_CYCLE); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_USB_IN_V_TRIGGER, &result, 1); value = (result) | FG_ADC_RR_USB_IN_V_EVERY_CYCLE; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_USB_IN_V_TRIGGER, &value, 1); if (rc < 0) { pr_err("Force every cycle update failed:%d\n", rc); goto fail; Loading @@ -853,8 +901,13 @@ static int rradc_do_conversion(struct rradc_chip *chip, } /* Restore usb_in trigger */ rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER, FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_USB_IN_V_TRIGGER, &result, 1); value = (result) & ~(FG_ADC_RR_USB_IN_V_EVERY_CYCLE); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_USB_IN_V_TRIGGER, &value, 1); if (rc < 0) { pr_err("Restore every cycle update failed:%d\n", rc); goto fail; Loading Loading @@ -1053,10 +1106,11 @@ static int rradc_get_dt_data(struct rradc_chip *chip, struct device_node *node) return 0; } static int rradc_probe(struct platform_device *pdev) static int rradc_probe(struct spmi_device *spmi) { struct device_node *node = pdev->dev.of_node; struct device *dev = &pdev->dev; struct device_node *node = spmi->dev.of_node; struct device *dev = &(spmi->dev); struct resource *res; struct iio_dev *indio_dev; struct rradc_chip *chip; int rc = 0; Loading @@ -1066,12 +1120,21 @@ static int rradc_probe(struct platform_device *pdev) return -ENOMEM; chip = iio_priv(indio_dev); chip->regmap = dev_get_regmap(pdev->dev.parent, NULL); chip->regmap = dev_get_regmap(&(spmi->dev), NULL); if (!chip->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); pr_debug("Couldn't get parent's regmap\n"); } chip->spmi = spmi; res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0); if (!res) { pr_err("RRADC No base address definition\n"); return -EINVAL; } chip->slave = spmi->sid; chip->offset = res->start; chip->dev = dev; mutex_init(&chip->lock); Loading @@ -1081,7 +1144,7 @@ static int rradc_probe(struct platform_device *pdev) indio_dev->dev.parent = dev; indio_dev->dev.of_node = node; indio_dev->name = pdev->name; indio_dev->name = spmi->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &rradc_info; indio_dev->channels = chip->iio_chans; Loading @@ -1094,16 +1157,26 @@ static const struct of_device_id rradc_match_table[] = { { .compatible = "qcom,rradc" }, { } }; MODULE_DEVICE_TABLE(of, rradc_match_table); static struct platform_driver rradc_driver = { static struct spmi_driver qpnp_rradc_driver = { .driver = { .name = "qcom-rradc", .of_match_table = rradc_match_table, }, .probe = rradc_probe, }; module_platform_driver(rradc_driver); static int __init qpnp_rradc_init(void) { return spmi_driver_register(&qpnp_rradc_driver); } module_init(qpnp_rradc_init); static void __exit qpnp_rradc_exit(void) { spmi_driver_unregister(&qpnp_rradc_driver); } module_exit(qpnp_rradc_exit); MODULE_DESCRIPTION("QPNP PMIC RR ADC driver"); MODULE_LICENSE("GPL v2"); drivers/power/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -71,7 +71,7 @@ obj-$(CONFIG_BATTERY_BQ28400) += bq28400_battery.o obj-$(CONFIG_QPNP_BMS) += qpnp-bms.o batterydata-lib.o obj-$(CONFIG_QPNP_VM_BMS) += qpnp-vm-bms.o batterydata-lib.o batterydata-interface.o obj-$(CONFIG_QPNP_FG) += qpnp-fg.o obj-$(CONFIG_QPNP_FG_GEN3) += qpnp-fg-gen3.o fg-memif.o fg-util.o obj-$(CONFIG_QPNP_FG_GEN3) += qpnp-fg-gen3.o fg-memif.o fg-util.o pmic-voter.o obj-$(CONFIG_QPNP_CHARGER) += qpnp-charger.o obj-$(CONFIG_QPNP_LINEAR_CHARGER) += qpnp-linear-charger.o obj-$(CONFIG_QPNP_SMBCHARGER) += qpnp-smbcharger.o pmic-voter.o Loading drivers/power/fg-core.h +4 −3 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/spmi.h> #include <linux/power_supply.h> #include <linux/regmap.h> #include <linux/slab.h> #include <linux/string_helpers.h> #include <linux/types.h> Loading Loading @@ -306,6 +306,7 @@ struct fg_irq_info { const irq_handler_t handler; bool wakeable; int irq; int flags; }; struct fg_circ_buf { Loading Loading @@ -351,9 +352,9 @@ static const struct fg_pt fg_tsmc_osc_table[] = { struct fg_chip { struct device *dev; struct pmic_revid_data *pmic_rev_id; struct regmap *regmap; struct spmi_device *spmi; struct dentry *dfs_root; struct power_supply *fg_psy; struct power_supply fg_psy; struct power_supply *batt_psy; struct power_supply *usb_psy; struct power_supply *dc_psy; Loading drivers/power/fg-util.c +34 −23 Original line number Diff line number Diff line Loading @@ -353,15 +353,14 @@ int fg_sram_masked_write(struct fg_chip *chip, u16 address, u8 offset, int fg_read(struct fg_chip *chip, int addr, u8 *val, int len) { int rc, i; struct spmi_device *spmi = chip->spmi; if (!chip || !chip->regmap) if (!chip || !chip->spmi) return -ENXIO; rc = regmap_bulk_read(chip->regmap, addr, val, len); if (rc < 0) { dev_err(chip->dev, "regmap_read failed for address %04x rc=%d\n", addr, rc); rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, len); if (rc) { pr_err("SPMI read failed addr=0x%02x rc=%d\n", addr, rc); return rc; } Loading @@ -378,26 +377,25 @@ int fg_write(struct fg_chip *chip, int addr, u8 *val, int len) { int rc, i; bool sec_access = false; u8 sec_addr_val = 0xA5; struct spmi_device *spmi = chip->spmi; if (!chip || !chip->regmap) if (!chip || !chip->spmi) return -ENXIO; mutex_lock(&chip->bus_lock); sec_access = (addr & 0x00FF) > 0xD0; if (sec_access) { rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5); rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, (addr & 0xFF00) | 0xD0, &sec_addr_val, 1); if (rc < 0) { dev_err(chip->dev, "regmap_write failed for address %x rc=%d\n", pr_err("SPMI write failed addr=0x%02x rc=%d\n", addr, rc); goto out; } } if (len > 1) rc = regmap_bulk_write(chip->regmap, addr, val, len); else rc = regmap_write(chip->regmap, addr, *val); rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, len); if (rc < 0) { dev_err(chip->dev, "regmap_write failed for address %04x rc=%d\n", addr, rc); Loading @@ -418,30 +416,43 @@ int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val) { int rc; bool sec_access = false; u8 reg, sec_addr_val = 0xA5; struct spmi_device *spmi = chip->spmi; if (!chip || !chip->regmap) if (!chip || !chip->spmi) return -ENXIO; mutex_lock(&chip->bus_lock); rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, ®, 1); if (rc) { pr_err("SPMI read failed addr=0x%02x rc=%d\n", addr, rc); goto out; } reg &= ~mask; reg |= val & mask; sec_access = (addr & 0x00FF) > 0xD0; if (sec_access) { rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5); rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, (addr & 0xFF00) | 0xD0, &sec_addr_val, 1); if (rc < 0) { dev_err(chip->dev, "regmap_write failed for address %x rc=%d\n", pr_err("SPMI write failed addr=0x%02x rc=%d\n", addr, rc); goto out; } } rc = regmap_update_bits(chip->regmap, addr, mask, val); rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, ®, 1); if (rc < 0) { dev_err(chip->dev, "regmap_update_bits failed for address %04x rc=%d\n", dev_err(chip->dev, "regmap_write failed for address %04x rc=%d\n", addr, rc); goto out; } fg_dbg(chip, FG_BUS_WRITE, "addr=%04x mask: %02x val: %02x\n", addr, mask, val); if (*chip->debug_mask & FG_BUS_WRITE) pr_info("addr=%04x val=%04x\n", addr, val); out: mutex_unlock(&chip->bus_lock); return rc; Loading Loading
arch/arm/boot/dts/qcom/msm-pm660.dtsi +74 −0 Original line number Diff line number Diff line Loading @@ -302,6 +302,7 @@ }; pm660_charger: qcom,qpnp-smb2 { spmi-dev-container; compatible = "qcom,qpnp-smb2"; #address-cells = <1>; #size-cells = <1>; Loading Loading @@ -424,6 +425,79 @@ }; }; pm660_rradc: rradc@4500 { compatible = "qcom,rradc"; reg = <0x4500 0x100>; #address-cells = <1>; #size-cells = <0>; #io-channel-cells = <1>; qcom,pmic-revid = <&pm660_revid>; }; pm660_fg: qpnp,fg { spmi-dev-container; compatible = "qcom,fg-gen3"; #address-cells = <1>; #size-cells = <1>; qcom,pmic-revid = <&pm660_revid>; io-channels = <&pm660_rradc 0>, <&pm660_rradc 7>; io-channel-names = "rradc_batt_id", "rradc_die_temp"; qcom,rradc-base = <0x4500>; qcom,fg-esr-timer-awake = <96 96>; qcom,fg-esr-timer-asleep = <256 256>; qcom,fg-esr-timer-charging = <0 96>; qcom,cycle-counter-en; status = "okay"; qcom,fg-batt-soc@4000 { status = "okay"; reg = <0x4000 0x100>; interrupts = <0x0 0x40 0x0>, <0x0 0x40 0x1>, <0x0 0x40 0x2>, <0x0 0x40 0x3>, <0x0 0x40 0x4>, <0x0 0x40 0x5>, <0x0 0x40 0x6>, <0x0 0x40 0x7>; interrupt-names = "soc-update", "soc-ready", "bsoc-delta", "msoc-delta", "msoc-low", "msoc-empty", "msoc-high", "msoc-full"; }; qcom,fg-batt-info@4100 { status = "okay"; reg = <0x4100 0x100>; interrupts = <0x0 0x41 0x0>, <0x0 0x41 0x1>, <0x0 0x41 0x2>, <0x0 0x41 0x3>, <0x0 0x41 0x6>; interrupt-names = "vbatt-pred-delta", "vbatt-low", "esr-delta", "batt-missing", "batt-temp-delta"; }; qcom,fg-memif@4400 { status = "okay"; reg = <0x4400 0x100>; interrupts = <0x0 0x44 0x0>, <0x0 0x44 0x1>, <0x0 0x44 0x2>; interrupt-names = "ima-rdy", "mem-xcp", "dma-grant"; }; }; pm660_pbs: qcom,pbs@7300 { compatible = "qcom,qpnp-pbs"; Loading
drivers/iio/adc/qcom-rradc.c +116 −43 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/regmap.h> #include <linux/delay.h> #include <linux/qpnp/qpnp-revid.h> #include <linux/spmi.h> #define FG_ADC_RR_EN_CTL 0x46 #define FG_ADC_RR_SKIN_TEMP_LSB 0x50 Loading Loading @@ -223,6 +224,9 @@ struct rradc_chip { struct mutex lock; struct regmap *regmap; u16 base; struct spmi_device *spmi; u8 slave; u16 offset; struct iio_chan_spec *iio_chans; unsigned int nchannels; struct rradc_chan_prop *chan_props; Loading @@ -248,21 +252,36 @@ struct rradc_chan_prop { u16 adc_code, int *result); }; static int rradc_masked_write(struct rradc_chip *rr_adc, u16 offset, u8 mask, u8 val) static int rradc_spmi_read(struct rradc_chip *rr_adc, unsigned int reg, u8 *data, int len) { int rc; rc = regmap_update_bits(rr_adc->regmap, rr_adc->base + offset, mask, val); if (rc) { pr_err("spmi write failed: addr=%03X, rc=%d\n", offset, rc); rc = spmi_ext_register_readl(rr_adc->spmi->ctrl, rr_adc->slave, reg, data, len); if (rc < 0) { pr_err("rradc spmi read reg %x failed with %d\n", reg, rc); return rc; } return 0; } static int rradc_spmi_write(struct rradc_chip *rr_adc, u16 reg, u8 *buf, int len) { int rc; rc = spmi_ext_register_writel(rr_adc->spmi->ctrl, rr_adc->slave, reg, buf, len); if (rc < 0) { pr_err("rradc spmi write reg %d failed with %d\n", reg, rc); return rc; } return 0; } static int rradc_read(struct rradc_chip *rr_adc, u16 offset, u8 *data, int len) { int rc = 0, retry_cnt = 0, i = 0; Loading @@ -275,14 +294,14 @@ static int rradc_read(struct rradc_chip *rr_adc, u16 offset, u8 *data, int len) } while (retry_cnt < FG_RR_ADC_COHERENT_CHECK_RETRY) { rc = regmap_bulk_read(rr_adc->regmap, rr_adc->base + offset, rc = rradc_spmi_read(rr_adc, rr_adc->base + offset, data, len); if (rc < 0) { pr_err("rr_adc reg 0x%x failed :%d\n", offset, rc); return rc; } rc = regmap_bulk_read(rr_adc->regmap, rr_adc->base + offset, rc = rradc_spmi_read(rr_adc, rr_adc->base + offset, data_check, len); if (rc < 0) { pr_err("rr_adc reg 0x%x failed :%d\n", offset, rc); Loading Loading @@ -635,27 +654,35 @@ static const struct rradc_channels rradc_chans[] = { static int rradc_enable_continuous_mode(struct rradc_chip *chip) { int rc = 0; u8 result, value; /* Clear channel log */ rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG, FG_ADC_RR_ADC_LOG_CLR_CTRL, FG_ADC_RR_ADC_LOG_CLR_CTRL); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_ADC_LOG, &result, 1); value = (result) | FG_ADC_RR_ADC_LOG_CLR_CTRL; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_ADC_LOG, &value, 1); if (rc < 0) { pr_err("log ctrl update to clear failed:%d\n", rc); return rc; } rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG, FG_ADC_RR_ADC_LOG_CLR_CTRL, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_ADC_LOG, &result, 1); value = (result) & ~(FG_ADC_RR_ADC_LOG_CLR_CTRL); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_ADC_LOG, &value, 1); if (rc < 0) { pr_err("log ctrl update to not clear failed:%d\n", rc); return rc; } /* Switch to continuous mode */ rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL, FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK, FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_RR_ADC_CTL, &result, 1); value = (result) | FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_RR_ADC_CTL, &value, 1); if (rc < 0) { pr_err("Update to continuous mode failed:%d\n", rc); return rc; Loading @@ -667,10 +694,14 @@ static int rradc_enable_continuous_mode(struct rradc_chip *chip) static int rradc_disable_continuous_mode(struct rradc_chip *chip) { int rc = 0; u8 result, value; /* Switch to non continuous mode */ rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL, FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_RR_ADC_CTL, &result, 1); value = (result) & ~(FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_RR_ADC_CTL, &value, 1); if (rc < 0) { pr_err("Update to non-continuous mode failed:%d\n", rc); return rc; Loading Loading @@ -752,18 +783,24 @@ static int rradc_read_channel_with_continuous_mode(struct rradc_chip *chip, static int rradc_enable_batt_id_channel(struct rradc_chip *chip, bool enable) { int rc = 0; u8 result, value; if (enable) { rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_CTRL, FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV, FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL, &result, 1); value = (result) | FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL, &value, 1); if (rc < 0) { pr_err("Enabling BATT ID channel failed:%d\n", rc); return rc; } } else { rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_CTRL, FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL, &result, 1); value = (result) & ~(FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL, &value, 1); if (rc < 0) { pr_err("Disabling BATT ID channel failed:%d\n", rc); return rc; Loading @@ -777,6 +814,7 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip, struct rradc_chan_prop *prop, u16 *data, u8 *buf) { int rc = 0, ret = 0; u8 result, value; rc = rradc_enable_batt_id_channel(chip, true); if (rc < 0) { Loading @@ -784,9 +822,11 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip, return rc; } rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_TRIGGER, FG_ADC_RR_BATT_ID_TRIGGER_CTL, FG_ADC_RR_BATT_ID_TRIGGER_CTL); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER, &result, 1); value = (result) | FG_ADC_RR_BATT_ID_TRIGGER_CTL; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER, &value, 1); if (rc < 0) { pr_err("BATT_ID trigger set failed:%d\n", rc); ret = rc; Loading @@ -802,8 +842,11 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip, ret = rc; } rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_TRIGGER, FG_ADC_RR_BATT_ID_TRIGGER_CTL, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER, &result, 1); value = (result) & ~(FG_ADC_RR_BATT_ID_TRIGGER_CTL); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER, &value, 1); if (rc < 0) { pr_err("BATT_ID trigger re-set failed:%d\n", rc); ret = rc; Loading @@ -825,6 +868,7 @@ static int rradc_do_conversion(struct rradc_chip *chip, u8 buf[6]; u16 offset = 0, batt_id_5 = 0, batt_id_15 = 0, batt_id_150 = 0; u16 status = 0; u8 result, value; mutex_lock(&chip->lock); Loading @@ -838,9 +882,13 @@ static int rradc_do_conversion(struct rradc_chip *chip, break; case RR_ADC_USBIN_V: /* Force conversion every cycle */ rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER, FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK, FG_ADC_RR_USB_IN_V_EVERY_CYCLE); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_USB_IN_V_TRIGGER, &result, 1); value = (result) | FG_ADC_RR_USB_IN_V_EVERY_CYCLE; rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_USB_IN_V_TRIGGER, &value, 1); if (rc < 0) { pr_err("Force every cycle update failed:%d\n", rc); goto fail; Loading @@ -853,8 +901,13 @@ static int rradc_do_conversion(struct rradc_chip *chip, } /* Restore usb_in trigger */ rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER, FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK, 0); rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_USB_IN_V_TRIGGER, &result, 1); value = (result) & ~(FG_ADC_RR_USB_IN_V_EVERY_CYCLE); rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_USB_IN_V_TRIGGER, &value, 1); if (rc < 0) { pr_err("Restore every cycle update failed:%d\n", rc); goto fail; Loading Loading @@ -1053,10 +1106,11 @@ static int rradc_get_dt_data(struct rradc_chip *chip, struct device_node *node) return 0; } static int rradc_probe(struct platform_device *pdev) static int rradc_probe(struct spmi_device *spmi) { struct device_node *node = pdev->dev.of_node; struct device *dev = &pdev->dev; struct device_node *node = spmi->dev.of_node; struct device *dev = &(spmi->dev); struct resource *res; struct iio_dev *indio_dev; struct rradc_chip *chip; int rc = 0; Loading @@ -1066,12 +1120,21 @@ static int rradc_probe(struct platform_device *pdev) return -ENOMEM; chip = iio_priv(indio_dev); chip->regmap = dev_get_regmap(pdev->dev.parent, NULL); chip->regmap = dev_get_regmap(&(spmi->dev), NULL); if (!chip->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); pr_debug("Couldn't get parent's regmap\n"); } chip->spmi = spmi; res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0); if (!res) { pr_err("RRADC No base address definition\n"); return -EINVAL; } chip->slave = spmi->sid; chip->offset = res->start; chip->dev = dev; mutex_init(&chip->lock); Loading @@ -1081,7 +1144,7 @@ static int rradc_probe(struct platform_device *pdev) indio_dev->dev.parent = dev; indio_dev->dev.of_node = node; indio_dev->name = pdev->name; indio_dev->name = spmi->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &rradc_info; indio_dev->channels = chip->iio_chans; Loading @@ -1094,16 +1157,26 @@ static const struct of_device_id rradc_match_table[] = { { .compatible = "qcom,rradc" }, { } }; MODULE_DEVICE_TABLE(of, rradc_match_table); static struct platform_driver rradc_driver = { static struct spmi_driver qpnp_rradc_driver = { .driver = { .name = "qcom-rradc", .of_match_table = rradc_match_table, }, .probe = rradc_probe, }; module_platform_driver(rradc_driver); static int __init qpnp_rradc_init(void) { return spmi_driver_register(&qpnp_rradc_driver); } module_init(qpnp_rradc_init); static void __exit qpnp_rradc_exit(void) { spmi_driver_unregister(&qpnp_rradc_driver); } module_exit(qpnp_rradc_exit); MODULE_DESCRIPTION("QPNP PMIC RR ADC driver"); MODULE_LICENSE("GPL v2");
drivers/power/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -71,7 +71,7 @@ obj-$(CONFIG_BATTERY_BQ28400) += bq28400_battery.o obj-$(CONFIG_QPNP_BMS) += qpnp-bms.o batterydata-lib.o obj-$(CONFIG_QPNP_VM_BMS) += qpnp-vm-bms.o batterydata-lib.o batterydata-interface.o obj-$(CONFIG_QPNP_FG) += qpnp-fg.o obj-$(CONFIG_QPNP_FG_GEN3) += qpnp-fg-gen3.o fg-memif.o fg-util.o obj-$(CONFIG_QPNP_FG_GEN3) += qpnp-fg-gen3.o fg-memif.o fg-util.o pmic-voter.o obj-$(CONFIG_QPNP_CHARGER) += qpnp-charger.o obj-$(CONFIG_QPNP_LINEAR_CHARGER) += qpnp-linear-charger.o obj-$(CONFIG_QPNP_SMBCHARGER) += qpnp-smbcharger.o pmic-voter.o Loading
drivers/power/fg-core.h +4 −3 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/spmi.h> #include <linux/power_supply.h> #include <linux/regmap.h> #include <linux/slab.h> #include <linux/string_helpers.h> #include <linux/types.h> Loading Loading @@ -306,6 +306,7 @@ struct fg_irq_info { const irq_handler_t handler; bool wakeable; int irq; int flags; }; struct fg_circ_buf { Loading Loading @@ -351,9 +352,9 @@ static const struct fg_pt fg_tsmc_osc_table[] = { struct fg_chip { struct device *dev; struct pmic_revid_data *pmic_rev_id; struct regmap *regmap; struct spmi_device *spmi; struct dentry *dfs_root; struct power_supply *fg_psy; struct power_supply fg_psy; struct power_supply *batt_psy; struct power_supply *usb_psy; struct power_supply *dc_psy; Loading
drivers/power/fg-util.c +34 −23 Original line number Diff line number Diff line Loading @@ -353,15 +353,14 @@ int fg_sram_masked_write(struct fg_chip *chip, u16 address, u8 offset, int fg_read(struct fg_chip *chip, int addr, u8 *val, int len) { int rc, i; struct spmi_device *spmi = chip->spmi; if (!chip || !chip->regmap) if (!chip || !chip->spmi) return -ENXIO; rc = regmap_bulk_read(chip->regmap, addr, val, len); if (rc < 0) { dev_err(chip->dev, "regmap_read failed for address %04x rc=%d\n", addr, rc); rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, len); if (rc) { pr_err("SPMI read failed addr=0x%02x rc=%d\n", addr, rc); return rc; } Loading @@ -378,26 +377,25 @@ int fg_write(struct fg_chip *chip, int addr, u8 *val, int len) { int rc, i; bool sec_access = false; u8 sec_addr_val = 0xA5; struct spmi_device *spmi = chip->spmi; if (!chip || !chip->regmap) if (!chip || !chip->spmi) return -ENXIO; mutex_lock(&chip->bus_lock); sec_access = (addr & 0x00FF) > 0xD0; if (sec_access) { rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5); rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, (addr & 0xFF00) | 0xD0, &sec_addr_val, 1); if (rc < 0) { dev_err(chip->dev, "regmap_write failed for address %x rc=%d\n", pr_err("SPMI write failed addr=0x%02x rc=%d\n", addr, rc); goto out; } } if (len > 1) rc = regmap_bulk_write(chip->regmap, addr, val, len); else rc = regmap_write(chip->regmap, addr, *val); rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, len); if (rc < 0) { dev_err(chip->dev, "regmap_write failed for address %04x rc=%d\n", addr, rc); Loading @@ -418,30 +416,43 @@ int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val) { int rc; bool sec_access = false; u8 reg, sec_addr_val = 0xA5; struct spmi_device *spmi = chip->spmi; if (!chip || !chip->regmap) if (!chip || !chip->spmi) return -ENXIO; mutex_lock(&chip->bus_lock); rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, ®, 1); if (rc) { pr_err("SPMI read failed addr=0x%02x rc=%d\n", addr, rc); goto out; } reg &= ~mask; reg |= val & mask; sec_access = (addr & 0x00FF) > 0xD0; if (sec_access) { rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5); rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, (addr & 0xFF00) | 0xD0, &sec_addr_val, 1); if (rc < 0) { dev_err(chip->dev, "regmap_write failed for address %x rc=%d\n", pr_err("SPMI write failed addr=0x%02x rc=%d\n", addr, rc); goto out; } } rc = regmap_update_bits(chip->regmap, addr, mask, val); rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, ®, 1); if (rc < 0) { dev_err(chip->dev, "regmap_update_bits failed for address %04x rc=%d\n", dev_err(chip->dev, "regmap_write failed for address %04x rc=%d\n", addr, rc); goto out; } fg_dbg(chip, FG_BUS_WRITE, "addr=%04x mask: %02x val: %02x\n", addr, mask, val); if (*chip->debug_mask & FG_BUS_WRITE) pr_info("addr=%04x val=%04x\n", addr, val); out: mutex_unlock(&chip->bus_lock); return rc; Loading