355 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2022 Richtek Technology Corp.4 *5 * Author: ChiaEn Wu <chiaen_wu@richtek.com>6 */7 8#include <linux/bits.h>9#include <linux/bitfield.h>10#include <linux/iio/iio.h>11#include <linux/kernel.h>12#include <linux/mod_devicetable.h>13#include <linux/module.h>14#include <linux/mutex.h>15#include <linux/platform_device.h>16#include <linux/regmap.h>17#include <linux/sysfs.h>18#include <linux/units.h>19 20#include <dt-bindings/iio/adc/mediatek,mt6370_adc.h>21 22#define MT6370_REG_DEV_INFO 0x10023#define MT6370_REG_CHG_CTRL3 0x11324#define MT6370_REG_CHG_CTRL7 0x11725#define MT6370_REG_CHG_ADC 0x12126#define MT6370_REG_ADC_DATA_H 0x14C27 28#define MT6370_ADC_START_MASK BIT(0)29#define MT6370_ADC_IN_SEL_MASK GENMASK(7, 4)30#define MT6370_AICR_ICHG_MASK GENMASK(7, 2)31#define MT6370_VENID_MASK GENMASK(7, 4)32 33#define MT6370_AICR_100_mA 0x034#define MT6370_AICR_150_mA 0x135#define MT6370_AICR_200_mA 0x236#define MT6370_AICR_250_mA 0x337#define MT6370_AICR_300_mA 0x438#define MT6370_AICR_350_mA 0x539 40#define MT6370_ICHG_100_mA 0x041#define MT6370_ICHG_200_mA 0x142#define MT6370_ICHG_300_mA 0x243#define MT6370_ICHG_400_mA 0x344#define MT6370_ICHG_500_mA 0x445#define MT6370_ICHG_600_mA 0x546#define MT6370_ICHG_700_mA 0x647#define MT6370_ICHG_800_mA 0x748 49#define ADC_CONV_TIME_MS 3550#define ADC_CONV_POLLING_TIME_US 100051 52#define MT6370_VID_RT5081 0x853#define MT6370_VID_RT5081A 0xA54#define MT6370_VID_MT6370 0xE55 56struct mt6370_adc_data {57 struct device *dev;58 struct regmap *regmap;59 /*60 * This mutex lock is for preventing the different ADC channels61 * from being read at the same time.62 */63 struct mutex adc_lock;64 unsigned int vid;65};66 67static int mt6370_adc_read_channel(struct mt6370_adc_data *priv, int chan,68 unsigned long addr, int *val)69{70 unsigned int reg_val;71 __be16 be_val;72 int ret;73 74 mutex_lock(&priv->adc_lock);75 76 reg_val = MT6370_ADC_START_MASK |77 FIELD_PREP(MT6370_ADC_IN_SEL_MASK, addr);78 ret = regmap_write(priv->regmap, MT6370_REG_CHG_ADC, reg_val);79 if (ret)80 goto adc_unlock;81 82 msleep(ADC_CONV_TIME_MS);83 84 ret = regmap_read_poll_timeout(priv->regmap,85 MT6370_REG_CHG_ADC, reg_val,86 !(reg_val & MT6370_ADC_START_MASK),87 ADC_CONV_POLLING_TIME_US,88 ADC_CONV_TIME_MS * MILLI * 3);89 if (ret) {90 dev_err(priv->dev, "Failed to read ADC register (%d)\n", ret);91 goto adc_unlock;92 }93 94 ret = regmap_raw_read(priv->regmap, MT6370_REG_ADC_DATA_H,95 &be_val, sizeof(be_val));96 if (ret)97 goto adc_unlock;98 99 *val = be16_to_cpu(be_val);100 ret = IIO_VAL_INT;101 102adc_unlock:103 mutex_unlock(&priv->adc_lock);104 105 return ret;106}107 108static int mt6370_adc_get_ibus_scale(struct mt6370_adc_data *priv)109{110 switch (priv->vid) {111 case MT6370_VID_RT5081:112 case MT6370_VID_RT5081A:113 case MT6370_VID_MT6370:114 return 3350;115 default:116 return 3875;117 }118}119 120static int mt6370_adc_get_ibat_scale(struct mt6370_adc_data *priv)121{122 switch (priv->vid) {123 case MT6370_VID_RT5081:124 case MT6370_VID_RT5081A:125 case MT6370_VID_MT6370:126 return 2680;127 default:128 return 3870;129 }130}131 132static int mt6370_adc_read_scale(struct mt6370_adc_data *priv,133 int chan, int *val1, int *val2)134{135 unsigned int reg_val;136 int ret;137 138 switch (chan) {139 case MT6370_CHAN_VBAT:140 case MT6370_CHAN_VSYS:141 case MT6370_CHAN_CHG_VDDP:142 *val1 = 5;143 return IIO_VAL_INT;144 case MT6370_CHAN_IBUS:145 ret = regmap_read(priv->regmap, MT6370_REG_CHG_CTRL3, ®_val);146 if (ret)147 return ret;148 149 reg_val = FIELD_GET(MT6370_AICR_ICHG_MASK, reg_val);150 switch (reg_val) {151 case MT6370_AICR_100_mA:152 case MT6370_AICR_150_mA:153 case MT6370_AICR_200_mA:154 case MT6370_AICR_250_mA:155 case MT6370_AICR_300_mA:156 case MT6370_AICR_350_mA:157 *val1 = mt6370_adc_get_ibus_scale(priv);158 break;159 default:160 *val1 = 5000;161 break;162 }163 164 *val2 = 100;165 166 return IIO_VAL_FRACTIONAL;167 case MT6370_CHAN_IBAT:168 ret = regmap_read(priv->regmap, MT6370_REG_CHG_CTRL7, ®_val);169 if (ret)170 return ret;171 172 reg_val = FIELD_GET(MT6370_AICR_ICHG_MASK, reg_val);173 switch (reg_val) {174 case MT6370_ICHG_100_mA:175 case MT6370_ICHG_200_mA:176 case MT6370_ICHG_300_mA:177 case MT6370_ICHG_400_mA:178 *val1 = 2375;179 break;180 case MT6370_ICHG_500_mA:181 case MT6370_ICHG_600_mA:182 case MT6370_ICHG_700_mA:183 case MT6370_ICHG_800_mA:184 *val1 = mt6370_adc_get_ibat_scale(priv);185 break;186 default:187 *val1 = 5000;188 break;189 }190 191 *val2 = 100;192 193 return IIO_VAL_FRACTIONAL;194 case MT6370_CHAN_VBUSDIV5:195 *val1 = 25;196 return IIO_VAL_INT;197 case MT6370_CHAN_VBUSDIV2:198 *val1 = 10;199 return IIO_VAL_INT;200 case MT6370_CHAN_TS_BAT:201 *val1 = 25;202 *val2 = 10000;203 return IIO_VAL_FRACTIONAL;204 case MT6370_CHAN_TEMP_JC:205 *val1 = 2000;206 return IIO_VAL_INT;207 default:208 return -EINVAL;209 }210}211 212static int mt6370_adc_read_offset(struct mt6370_adc_data *priv,213 int chan, int *val)214{215 *val = -20;216 217 return IIO_VAL_INT;218}219 220static int mt6370_adc_read_raw(struct iio_dev *iio_dev,221 const struct iio_chan_spec *chan,222 int *val, int *val2, long mask)223{224 struct mt6370_adc_data *priv = iio_priv(iio_dev);225 226 switch (mask) {227 case IIO_CHAN_INFO_RAW:228 return mt6370_adc_read_channel(priv, chan->channel,229 chan->address, val);230 case IIO_CHAN_INFO_SCALE:231 return mt6370_adc_read_scale(priv, chan->channel, val, val2);232 case IIO_CHAN_INFO_OFFSET:233 return mt6370_adc_read_offset(priv, chan->channel, val);234 default:235 return -EINVAL;236 }237}238 239static const char * const mt6370_channel_labels[MT6370_CHAN_MAX] = {240 [MT6370_CHAN_VBUSDIV5] = "vbusdiv5",241 [MT6370_CHAN_VBUSDIV2] = "vbusdiv2",242 [MT6370_CHAN_VSYS] = "vsys",243 [MT6370_CHAN_VBAT] = "vbat",244 [MT6370_CHAN_TS_BAT] = "ts_bat",245 [MT6370_CHAN_IBUS] = "ibus",246 [MT6370_CHAN_IBAT] = "ibat",247 [MT6370_CHAN_CHG_VDDP] = "chg_vddp",248 [MT6370_CHAN_TEMP_JC] = "temp_jc",249};250 251static int mt6370_adc_read_label(struct iio_dev *iio_dev,252 struct iio_chan_spec const *chan, char *label)253{254 return sysfs_emit(label, "%s\n", mt6370_channel_labels[chan->channel]);255}256 257static const struct iio_info mt6370_adc_iio_info = {258 .read_raw = mt6370_adc_read_raw,259 .read_label = mt6370_adc_read_label,260};261 262#define MT6370_ADC_CHAN(_idx, _type, _addr, _extra_info) { \263 .type = _type, \264 .channel = MT6370_CHAN_##_idx, \265 .address = _addr, \266 .scan_index = MT6370_CHAN_##_idx, \267 .indexed = 1, \268 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \269 BIT(IIO_CHAN_INFO_SCALE) | \270 _extra_info, \271}272 273static const struct iio_chan_spec mt6370_adc_channels[] = {274 MT6370_ADC_CHAN(VBUSDIV5, IIO_VOLTAGE, 1, 0),275 MT6370_ADC_CHAN(VBUSDIV2, IIO_VOLTAGE, 2, 0),276 MT6370_ADC_CHAN(VSYS, IIO_VOLTAGE, 3, 0),277 MT6370_ADC_CHAN(VBAT, IIO_VOLTAGE, 4, 0),278 MT6370_ADC_CHAN(TS_BAT, IIO_VOLTAGE, 6, 0),279 MT6370_ADC_CHAN(IBUS, IIO_CURRENT, 8, 0),280 MT6370_ADC_CHAN(IBAT, IIO_CURRENT, 9, 0),281 MT6370_ADC_CHAN(CHG_VDDP, IIO_VOLTAGE, 11, 0),282 MT6370_ADC_CHAN(TEMP_JC, IIO_TEMP, 12, BIT(IIO_CHAN_INFO_OFFSET)),283};284 285static int mt6370_get_vendor_info(struct mt6370_adc_data *priv)286{287 unsigned int dev_info;288 int ret;289 290 ret = regmap_read(priv->regmap, MT6370_REG_DEV_INFO, &dev_info);291 if (ret)292 return ret;293 294 priv->vid = FIELD_GET(MT6370_VENID_MASK, dev_info);295 296 return 0;297}298 299static int mt6370_adc_probe(struct platform_device *pdev)300{301 struct device *dev = &pdev->dev;302 struct mt6370_adc_data *priv;303 struct iio_dev *indio_dev;304 struct regmap *regmap;305 int ret;306 307 regmap = dev_get_regmap(pdev->dev.parent, NULL);308 if (!regmap)309 return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n");310 311 indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));312 if (!indio_dev)313 return -ENOMEM;314 315 priv = iio_priv(indio_dev);316 priv->dev = dev;317 priv->regmap = regmap;318 mutex_init(&priv->adc_lock);319 320 ret = mt6370_get_vendor_info(priv);321 if (ret)322 return dev_err_probe(dev, ret, "Failed to get vid\n");323 324 ret = regmap_write(priv->regmap, MT6370_REG_CHG_ADC, 0);325 if (ret)326 return dev_err_probe(dev, ret, "Failed to reset ADC\n");327 328 indio_dev->name = "mt6370-adc";329 indio_dev->info = &mt6370_adc_iio_info;330 indio_dev->modes = INDIO_DIRECT_MODE;331 indio_dev->channels = mt6370_adc_channels;332 indio_dev->num_channels = ARRAY_SIZE(mt6370_adc_channels);333 334 return devm_iio_device_register(dev, indio_dev);335}336 337static const struct of_device_id mt6370_adc_of_id[] = {338 { .compatible = "mediatek,mt6370-adc", },339 {}340};341MODULE_DEVICE_TABLE(of, mt6370_adc_of_id);342 343static struct platform_driver mt6370_adc_driver = {344 .driver = {345 .name = "mt6370-adc",346 .of_match_table = mt6370_adc_of_id,347 },348 .probe = mt6370_adc_probe,349};350module_platform_driver(mt6370_adc_driver);351 352MODULE_AUTHOR("ChiaEn Wu <chiaen_wu@richtek.com>");353MODULE_DESCRIPTION("MT6370 ADC Driver");354MODULE_LICENSE("GPL v2");355