brintos

brintos / linux-shallow public Read only

0
0
Text · 8.4 KiB · 0bc1121 Raw
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, &reg_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, &reg_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