xref: /openbmc/u-boot/drivers/adc/adc-uclass.c (revision e070dc422d98cd232a928ceba87ac448854b8f25)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
25decbf53SPrzemyslaw Marczak /*
35decbf53SPrzemyslaw Marczak  * Copyright (C) 2015 Samsung Electronics
45decbf53SPrzemyslaw Marczak  * Przemyslaw Marczak <p.marczak@samsung.com>
55decbf53SPrzemyslaw Marczak  */
65decbf53SPrzemyslaw Marczak 
75decbf53SPrzemyslaw Marczak #include <common.h>
85decbf53SPrzemyslaw Marczak #include <errno.h>
9*63f004e7SFabrice Gasnier #include <div64.h>
105decbf53SPrzemyslaw Marczak #include <dm.h>
115decbf53SPrzemyslaw Marczak #include <dm/lists.h>
125decbf53SPrzemyslaw Marczak #include <dm/device-internal.h>
135decbf53SPrzemyslaw Marczak #include <dm/uclass-internal.h>
145decbf53SPrzemyslaw Marczak #include <adc.h>
155decbf53SPrzemyslaw Marczak #include <power/regulator.h>
165decbf53SPrzemyslaw Marczak 
175decbf53SPrzemyslaw Marczak #define ADC_UCLASS_PLATDATA_SIZE	sizeof(struct adc_uclass_platdata)
185decbf53SPrzemyslaw Marczak #define CHECK_NUMBER			true
195decbf53SPrzemyslaw Marczak #define CHECK_MASK			(!CHECK_NUMBER)
205decbf53SPrzemyslaw Marczak 
215decbf53SPrzemyslaw Marczak /* TODO: add support for timer uclass (for early calls) */
225decbf53SPrzemyslaw Marczak #ifdef CONFIG_SANDBOX_ARCH
235decbf53SPrzemyslaw Marczak #define sdelay(x)	udelay(x)
245decbf53SPrzemyslaw Marczak #else
255decbf53SPrzemyslaw Marczak extern void sdelay(unsigned long loops);
265decbf53SPrzemyslaw Marczak #endif
275decbf53SPrzemyslaw Marczak 
check_channel(struct udevice * dev,int value,bool number_or_mask,const char * caller_function)285decbf53SPrzemyslaw Marczak static int check_channel(struct udevice *dev, int value, bool number_or_mask,
295decbf53SPrzemyslaw Marczak 			 const char *caller_function)
305decbf53SPrzemyslaw Marczak {
315decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
325decbf53SPrzemyslaw Marczak 	unsigned mask = number_or_mask ? (1 << value) : value;
335decbf53SPrzemyslaw Marczak 
345decbf53SPrzemyslaw Marczak 	/* For the real ADC hardware, some ADC channels can be inactive.
355decbf53SPrzemyslaw Marczak 	 * For example if device has 4 analog channels, and only channels
365decbf53SPrzemyslaw Marczak 	 * 1-st and 3-rd are valid, then channel mask is: 0b1010, so request
375decbf53SPrzemyslaw Marczak 	 * with mask 0b1110 should return an error.
385decbf53SPrzemyslaw Marczak 	*/
395decbf53SPrzemyslaw Marczak 	if ((uc_pdata->channel_mask >= mask) && (uc_pdata->channel_mask & mask))
405decbf53SPrzemyslaw Marczak 		return 0;
415decbf53SPrzemyslaw Marczak 
425decbf53SPrzemyslaw Marczak 	printf("Error in %s/%s().\nWrong channel selection for device: %s\n",
435decbf53SPrzemyslaw Marczak 	       __FILE__, caller_function, dev->name);
445decbf53SPrzemyslaw Marczak 
455decbf53SPrzemyslaw Marczak 	return -EINVAL;
465decbf53SPrzemyslaw Marczak }
475decbf53SPrzemyslaw Marczak 
adc_supply_enable(struct udevice * dev)485decbf53SPrzemyslaw Marczak static int adc_supply_enable(struct udevice *dev)
495decbf53SPrzemyslaw Marczak {
505decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
515decbf53SPrzemyslaw Marczak 	const char *supply_type;
525decbf53SPrzemyslaw Marczak 	int ret = 0;
535decbf53SPrzemyslaw Marczak 
545decbf53SPrzemyslaw Marczak 	if (uc_pdata->vdd_supply) {
555decbf53SPrzemyslaw Marczak 		supply_type = "vdd";
565decbf53SPrzemyslaw Marczak 		ret = regulator_set_enable(uc_pdata->vdd_supply, true);
575decbf53SPrzemyslaw Marczak 	}
585decbf53SPrzemyslaw Marczak 
595decbf53SPrzemyslaw Marczak 	if (!ret && uc_pdata->vss_supply) {
605decbf53SPrzemyslaw Marczak 		supply_type = "vss";
615decbf53SPrzemyslaw Marczak 		ret = regulator_set_enable(uc_pdata->vss_supply, true);
625decbf53SPrzemyslaw Marczak 	}
635decbf53SPrzemyslaw Marczak 
645decbf53SPrzemyslaw Marczak 	if (ret)
659b643e31SMasahiro Yamada 		pr_err("%s: can't enable %s-supply!", dev->name, supply_type);
665decbf53SPrzemyslaw Marczak 
675decbf53SPrzemyslaw Marczak 	return ret;
685decbf53SPrzemyslaw Marczak }
695decbf53SPrzemyslaw Marczak 
adc_data_mask(struct udevice * dev,unsigned int * data_mask)705decbf53SPrzemyslaw Marczak int adc_data_mask(struct udevice *dev, unsigned int *data_mask)
715decbf53SPrzemyslaw Marczak {
725decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
735decbf53SPrzemyslaw Marczak 
745decbf53SPrzemyslaw Marczak 	if (!uc_pdata)
755decbf53SPrzemyslaw Marczak 		return -ENOSYS;
765decbf53SPrzemyslaw Marczak 
775decbf53SPrzemyslaw Marczak 	*data_mask = uc_pdata->data_mask;
785decbf53SPrzemyslaw Marczak 	return 0;
795decbf53SPrzemyslaw Marczak }
805decbf53SPrzemyslaw Marczak 
adc_channel_mask(struct udevice * dev,unsigned int * channel_mask)81*63f004e7SFabrice Gasnier int adc_channel_mask(struct udevice *dev, unsigned int *channel_mask)
82*63f004e7SFabrice Gasnier {
83*63f004e7SFabrice Gasnier 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
84*63f004e7SFabrice Gasnier 
85*63f004e7SFabrice Gasnier 	if (!uc_pdata)
86*63f004e7SFabrice Gasnier 		return -ENOSYS;
87*63f004e7SFabrice Gasnier 
88*63f004e7SFabrice Gasnier 	*channel_mask = uc_pdata->channel_mask;
89*63f004e7SFabrice Gasnier 
90*63f004e7SFabrice Gasnier 	return 0;
91*63f004e7SFabrice Gasnier }
92*63f004e7SFabrice Gasnier 
adc_stop(struct udevice * dev)935decbf53SPrzemyslaw Marczak int adc_stop(struct udevice *dev)
945decbf53SPrzemyslaw Marczak {
955decbf53SPrzemyslaw Marczak 	const struct adc_ops *ops = dev_get_driver_ops(dev);
965decbf53SPrzemyslaw Marczak 
975decbf53SPrzemyslaw Marczak 	if (!ops->stop)
985decbf53SPrzemyslaw Marczak 		return -ENOSYS;
995decbf53SPrzemyslaw Marczak 
1005decbf53SPrzemyslaw Marczak 	return ops->stop(dev);
1015decbf53SPrzemyslaw Marczak }
1025decbf53SPrzemyslaw Marczak 
adc_start_channel(struct udevice * dev,int channel)1035decbf53SPrzemyslaw Marczak int adc_start_channel(struct udevice *dev, int channel)
1045decbf53SPrzemyslaw Marczak {
1055decbf53SPrzemyslaw Marczak 	const struct adc_ops *ops = dev_get_driver_ops(dev);
1065decbf53SPrzemyslaw Marczak 	int ret;
1075decbf53SPrzemyslaw Marczak 
1085decbf53SPrzemyslaw Marczak 	if (!ops->start_channel)
1095decbf53SPrzemyslaw Marczak 		return -ENOSYS;
1105decbf53SPrzemyslaw Marczak 
1115decbf53SPrzemyslaw Marczak 	ret = check_channel(dev, channel, CHECK_NUMBER, __func__);
1125decbf53SPrzemyslaw Marczak 	if (ret)
1135decbf53SPrzemyslaw Marczak 		return ret;
1145decbf53SPrzemyslaw Marczak 
1155decbf53SPrzemyslaw Marczak 	ret = adc_supply_enable(dev);
1165decbf53SPrzemyslaw Marczak 	if (ret)
1175decbf53SPrzemyslaw Marczak 		return ret;
1185decbf53SPrzemyslaw Marczak 
1195decbf53SPrzemyslaw Marczak 	return ops->start_channel(dev, channel);
1205decbf53SPrzemyslaw Marczak }
1215decbf53SPrzemyslaw Marczak 
adc_start_channels(struct udevice * dev,unsigned int channel_mask)1225decbf53SPrzemyslaw Marczak int adc_start_channels(struct udevice *dev, unsigned int channel_mask)
1235decbf53SPrzemyslaw Marczak {
1245decbf53SPrzemyslaw Marczak 	const struct adc_ops *ops = dev_get_driver_ops(dev);
1255decbf53SPrzemyslaw Marczak 	int ret;
1265decbf53SPrzemyslaw Marczak 
1275decbf53SPrzemyslaw Marczak 	if (!ops->start_channels)
1285decbf53SPrzemyslaw Marczak 		return -ENOSYS;
1295decbf53SPrzemyslaw Marczak 
1305decbf53SPrzemyslaw Marczak 	ret = check_channel(dev, channel_mask, CHECK_MASK, __func__);
1315decbf53SPrzemyslaw Marczak 	if (ret)
1325decbf53SPrzemyslaw Marczak 		return ret;
1335decbf53SPrzemyslaw Marczak 
1345decbf53SPrzemyslaw Marczak 	ret = adc_supply_enable(dev);
1355decbf53SPrzemyslaw Marczak 	if (ret)
1365decbf53SPrzemyslaw Marczak 		return ret;
1375decbf53SPrzemyslaw Marczak 
1385decbf53SPrzemyslaw Marczak 	return ops->start_channels(dev, channel_mask);
1395decbf53SPrzemyslaw Marczak }
1405decbf53SPrzemyslaw Marczak 
adc_channel_data(struct udevice * dev,int channel,unsigned int * data)1415decbf53SPrzemyslaw Marczak int adc_channel_data(struct udevice *dev, int channel, unsigned int *data)
1425decbf53SPrzemyslaw Marczak {
1435decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
1445decbf53SPrzemyslaw Marczak 	const struct adc_ops *ops = dev_get_driver_ops(dev);
1455decbf53SPrzemyslaw Marczak 	unsigned int timeout_us = uc_pdata->data_timeout_us;
1465decbf53SPrzemyslaw Marczak 	int ret;
1475decbf53SPrzemyslaw Marczak 
1485decbf53SPrzemyslaw Marczak 	if (!ops->channel_data)
1495decbf53SPrzemyslaw Marczak 		return -ENOSYS;
1505decbf53SPrzemyslaw Marczak 
1515decbf53SPrzemyslaw Marczak 	ret = check_channel(dev, channel, CHECK_NUMBER, __func__);
1525decbf53SPrzemyslaw Marczak 	if (ret)
1535decbf53SPrzemyslaw Marczak 		return ret;
1545decbf53SPrzemyslaw Marczak 
1555decbf53SPrzemyslaw Marczak 	do {
1565decbf53SPrzemyslaw Marczak 		ret = ops->channel_data(dev, channel, data);
1575decbf53SPrzemyslaw Marczak 		if (!ret || ret != -EBUSY)
1585decbf53SPrzemyslaw Marczak 			break;
1595decbf53SPrzemyslaw Marczak 
1605decbf53SPrzemyslaw Marczak 		/* TODO: use timer uclass (for early calls). */
1615decbf53SPrzemyslaw Marczak 		sdelay(5);
1625decbf53SPrzemyslaw Marczak 	} while (timeout_us--);
1635decbf53SPrzemyslaw Marczak 
1645decbf53SPrzemyslaw Marczak 	return ret;
1655decbf53SPrzemyslaw Marczak }
1665decbf53SPrzemyslaw Marczak 
adc_channels_data(struct udevice * dev,unsigned int channel_mask,struct adc_channel * channels)1675decbf53SPrzemyslaw Marczak int adc_channels_data(struct udevice *dev, unsigned int channel_mask,
1685decbf53SPrzemyslaw Marczak 		      struct adc_channel *channels)
1695decbf53SPrzemyslaw Marczak {
1705decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
1715decbf53SPrzemyslaw Marczak 	unsigned int timeout_us = uc_pdata->multidata_timeout_us;
1725decbf53SPrzemyslaw Marczak 	const struct adc_ops *ops = dev_get_driver_ops(dev);
1735decbf53SPrzemyslaw Marczak 	int ret;
1745decbf53SPrzemyslaw Marczak 
1755decbf53SPrzemyslaw Marczak 	if (!ops->channels_data)
1765decbf53SPrzemyslaw Marczak 		return -ENOSYS;
1775decbf53SPrzemyslaw Marczak 
1785decbf53SPrzemyslaw Marczak 	ret = check_channel(dev, channel_mask, CHECK_MASK, __func__);
1795decbf53SPrzemyslaw Marczak 	if (ret)
1805decbf53SPrzemyslaw Marczak 		return ret;
1815decbf53SPrzemyslaw Marczak 
1825decbf53SPrzemyslaw Marczak 	do {
1835decbf53SPrzemyslaw Marczak 		ret = ops->channels_data(dev, channel_mask, channels);
1845decbf53SPrzemyslaw Marczak 		if (!ret || ret != -EBUSY)
1855decbf53SPrzemyslaw Marczak 			break;
1865decbf53SPrzemyslaw Marczak 
1875decbf53SPrzemyslaw Marczak 		/* TODO: use timer uclass (for early calls). */
1885decbf53SPrzemyslaw Marczak 		sdelay(5);
1895decbf53SPrzemyslaw Marczak 	} while (timeout_us--);
1905decbf53SPrzemyslaw Marczak 
1915decbf53SPrzemyslaw Marczak 	return ret;
1925decbf53SPrzemyslaw Marczak }
1935decbf53SPrzemyslaw Marczak 
adc_channel_single_shot(const char * name,int channel,unsigned int * data)1945decbf53SPrzemyslaw Marczak int adc_channel_single_shot(const char *name, int channel, unsigned int *data)
1955decbf53SPrzemyslaw Marczak {
1965decbf53SPrzemyslaw Marczak 	struct udevice *dev;
1975decbf53SPrzemyslaw Marczak 	int ret;
1985decbf53SPrzemyslaw Marczak 
1995decbf53SPrzemyslaw Marczak 	ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev);
2005decbf53SPrzemyslaw Marczak 	if (ret)
2015decbf53SPrzemyslaw Marczak 		return ret;
2025decbf53SPrzemyslaw Marczak 
2035decbf53SPrzemyslaw Marczak 	ret = adc_start_channel(dev, channel);
2045decbf53SPrzemyslaw Marczak 	if (ret)
2055decbf53SPrzemyslaw Marczak 		return ret;
2065decbf53SPrzemyslaw Marczak 
2075decbf53SPrzemyslaw Marczak 	ret = adc_channel_data(dev, channel, data);
2085decbf53SPrzemyslaw Marczak 	if (ret)
2095decbf53SPrzemyslaw Marczak 		return ret;
2105decbf53SPrzemyslaw Marczak 
2115decbf53SPrzemyslaw Marczak 	return 0;
2125decbf53SPrzemyslaw Marczak }
2135decbf53SPrzemyslaw Marczak 
_adc_channels_single_shot(struct udevice * dev,unsigned int channel_mask,struct adc_channel * channels)2145decbf53SPrzemyslaw Marczak static int _adc_channels_single_shot(struct udevice *dev,
2155decbf53SPrzemyslaw Marczak 				     unsigned int channel_mask,
2165decbf53SPrzemyslaw Marczak 				     struct adc_channel *channels)
2175decbf53SPrzemyslaw Marczak {
2185decbf53SPrzemyslaw Marczak 	unsigned int data;
2195decbf53SPrzemyslaw Marczak 	int channel, ret;
2205decbf53SPrzemyslaw Marczak 
2215decbf53SPrzemyslaw Marczak 	for (channel = 0; channel <= ADC_MAX_CHANNEL; channel++) {
2225decbf53SPrzemyslaw Marczak 		/* Check channel bit. */
2235decbf53SPrzemyslaw Marczak 		if (!((channel_mask >> channel) & 0x1))
2245decbf53SPrzemyslaw Marczak 			continue;
2255decbf53SPrzemyslaw Marczak 
2265decbf53SPrzemyslaw Marczak 		ret = adc_start_channel(dev, channel);
2275decbf53SPrzemyslaw Marczak 		if (ret)
2285decbf53SPrzemyslaw Marczak 			return ret;
2295decbf53SPrzemyslaw Marczak 
2305decbf53SPrzemyslaw Marczak 		ret = adc_channel_data(dev, channel, &data);
2315decbf53SPrzemyslaw Marczak 		if (ret)
2325decbf53SPrzemyslaw Marczak 			return ret;
2335decbf53SPrzemyslaw Marczak 
2345decbf53SPrzemyslaw Marczak 		channels->id = channel;
2355decbf53SPrzemyslaw Marczak 		channels->data = data;
2365decbf53SPrzemyslaw Marczak 		channels++;
2375decbf53SPrzemyslaw Marczak 	}
2385decbf53SPrzemyslaw Marczak 
2395decbf53SPrzemyslaw Marczak 	return 0;
2405decbf53SPrzemyslaw Marczak }
2415decbf53SPrzemyslaw Marczak 
adc_channels_single_shot(const char * name,unsigned int channel_mask,struct adc_channel * channels)2425decbf53SPrzemyslaw Marczak int adc_channels_single_shot(const char *name, unsigned int channel_mask,
2435decbf53SPrzemyslaw Marczak 			     struct adc_channel *channels)
2445decbf53SPrzemyslaw Marczak {
2455decbf53SPrzemyslaw Marczak 	struct udevice *dev;
2465decbf53SPrzemyslaw Marczak 	int ret;
2475decbf53SPrzemyslaw Marczak 
2485decbf53SPrzemyslaw Marczak 	ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev);
2495decbf53SPrzemyslaw Marczak 	if (ret)
2505decbf53SPrzemyslaw Marczak 		return ret;
2515decbf53SPrzemyslaw Marczak 
2525decbf53SPrzemyslaw Marczak 	ret = adc_start_channels(dev, channel_mask);
2535decbf53SPrzemyslaw Marczak 	if (ret)
2545decbf53SPrzemyslaw Marczak 		goto try_manual;
2555decbf53SPrzemyslaw Marczak 
2565decbf53SPrzemyslaw Marczak 	ret = adc_channels_data(dev, channel_mask, channels);
2575decbf53SPrzemyslaw Marczak 	if (ret)
2585decbf53SPrzemyslaw Marczak 		return ret;
2595decbf53SPrzemyslaw Marczak 
2605decbf53SPrzemyslaw Marczak 	return 0;
2615decbf53SPrzemyslaw Marczak 
2625decbf53SPrzemyslaw Marczak try_manual:
2635decbf53SPrzemyslaw Marczak 	if (ret != -ENOSYS)
2645decbf53SPrzemyslaw Marczak 		return ret;
2655decbf53SPrzemyslaw Marczak 
2665decbf53SPrzemyslaw Marczak 	return _adc_channels_single_shot(dev, channel_mask, channels);
2675decbf53SPrzemyslaw Marczak }
2685decbf53SPrzemyslaw Marczak 
adc_vdd_platdata_update(struct udevice * dev)2695decbf53SPrzemyslaw Marczak static int adc_vdd_platdata_update(struct udevice *dev)
2705decbf53SPrzemyslaw Marczak {
2715decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
2725decbf53SPrzemyslaw Marczak 	int ret;
2735decbf53SPrzemyslaw Marczak 
2745decbf53SPrzemyslaw Marczak 	/* Warning!
2755decbf53SPrzemyslaw Marczak 	 * This function can't return supply device before its bind.
2765decbf53SPrzemyslaw Marczak 	 * Please pay attention to proper fdt scan sequence. If ADC device
2775decbf53SPrzemyslaw Marczak 	 * will bind before its supply regulator device, then the below 'get'
2785decbf53SPrzemyslaw Marczak 	 * will return an error.
2795decbf53SPrzemyslaw Marczak 	 */
280a4a87f7bSFabrice Gasnier 	if (!uc_pdata->vdd_supply)
281a4a87f7bSFabrice Gasnier 		return 0;
2825decbf53SPrzemyslaw Marczak 
2835decbf53SPrzemyslaw Marczak 	ret = regulator_get_value(uc_pdata->vdd_supply);
2845decbf53SPrzemyslaw Marczak 	if (ret < 0)
2855decbf53SPrzemyslaw Marczak 		return ret;
2865decbf53SPrzemyslaw Marczak 
2875decbf53SPrzemyslaw Marczak 	uc_pdata->vdd_microvolts = ret;
2885decbf53SPrzemyslaw Marczak 
2895decbf53SPrzemyslaw Marczak 	return 0;
2905decbf53SPrzemyslaw Marczak }
2915decbf53SPrzemyslaw Marczak 
adc_vss_platdata_update(struct udevice * dev)2925decbf53SPrzemyslaw Marczak static int adc_vss_platdata_update(struct udevice *dev)
2935decbf53SPrzemyslaw Marczak {
2945decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
2955decbf53SPrzemyslaw Marczak 	int ret;
2965decbf53SPrzemyslaw Marczak 
297a4a87f7bSFabrice Gasnier 	if (!uc_pdata->vss_supply)
298a4a87f7bSFabrice Gasnier 		return 0;
2995decbf53SPrzemyslaw Marczak 
3005decbf53SPrzemyslaw Marczak 	ret = regulator_get_value(uc_pdata->vss_supply);
3015decbf53SPrzemyslaw Marczak 	if (ret < 0)
3025decbf53SPrzemyslaw Marczak 		return ret;
3035decbf53SPrzemyslaw Marczak 
3045decbf53SPrzemyslaw Marczak 	uc_pdata->vss_microvolts = ret;
3055decbf53SPrzemyslaw Marczak 
3065decbf53SPrzemyslaw Marczak 	return 0;
3075decbf53SPrzemyslaw Marczak }
3085decbf53SPrzemyslaw Marczak 
adc_vdd_value(struct udevice * dev,int * uV)3095decbf53SPrzemyslaw Marczak int adc_vdd_value(struct udevice *dev, int *uV)
3105decbf53SPrzemyslaw Marczak {
3115decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
3125decbf53SPrzemyslaw Marczak 	int ret, value_sign = uc_pdata->vdd_polarity_negative ? -1 : 1;
3135decbf53SPrzemyslaw Marczak 
3145decbf53SPrzemyslaw Marczak 	/* Update the regulator Value. */
3155decbf53SPrzemyslaw Marczak 	ret = adc_vdd_platdata_update(dev);
3165decbf53SPrzemyslaw Marczak 	if (ret)
3175decbf53SPrzemyslaw Marczak 		return ret;
318a4a87f7bSFabrice Gasnier 
3195decbf53SPrzemyslaw Marczak 	if (uc_pdata->vdd_microvolts == -ENODATA)
3205decbf53SPrzemyslaw Marczak 		return -ENODATA;
3215decbf53SPrzemyslaw Marczak 
3225decbf53SPrzemyslaw Marczak 	*uV = uc_pdata->vdd_microvolts * value_sign;
3235decbf53SPrzemyslaw Marczak 
3245decbf53SPrzemyslaw Marczak 	return 0;
3255decbf53SPrzemyslaw Marczak }
3265decbf53SPrzemyslaw Marczak 
adc_vss_value(struct udevice * dev,int * uV)3275decbf53SPrzemyslaw Marczak int adc_vss_value(struct udevice *dev, int *uV)
3285decbf53SPrzemyslaw Marczak {
3295decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
3305decbf53SPrzemyslaw Marczak 	int ret, value_sign = uc_pdata->vss_polarity_negative ? -1 : 1;
3315decbf53SPrzemyslaw Marczak 
3325decbf53SPrzemyslaw Marczak 	/* Update the regulator Value. */
3335decbf53SPrzemyslaw Marczak 	ret = adc_vss_platdata_update(dev);
3345decbf53SPrzemyslaw Marczak 	if (ret)
3355decbf53SPrzemyslaw Marczak 		return ret;
336a4a87f7bSFabrice Gasnier 
3375decbf53SPrzemyslaw Marczak 	if (uc_pdata->vss_microvolts == -ENODATA)
3385decbf53SPrzemyslaw Marczak 		return -ENODATA;
3395decbf53SPrzemyslaw Marczak 
3405decbf53SPrzemyslaw Marczak 	*uV = uc_pdata->vss_microvolts * value_sign;
3415decbf53SPrzemyslaw Marczak 
3425decbf53SPrzemyslaw Marczak 	return 0;
3435decbf53SPrzemyslaw Marczak }
3445decbf53SPrzemyslaw Marczak 
adc_raw_to_uV(struct udevice * dev,unsigned int raw,int * uV)345*63f004e7SFabrice Gasnier int adc_raw_to_uV(struct udevice *dev, unsigned int raw, int *uV)
346*63f004e7SFabrice Gasnier {
347*63f004e7SFabrice Gasnier 	unsigned int data_mask;
348*63f004e7SFabrice Gasnier 	int ret, val, vref;
349*63f004e7SFabrice Gasnier 	u64 raw64 = raw;
350*63f004e7SFabrice Gasnier 
351*63f004e7SFabrice Gasnier 	ret = adc_vdd_value(dev, &vref);
352*63f004e7SFabrice Gasnier 	if (ret)
353*63f004e7SFabrice Gasnier 		return ret;
354*63f004e7SFabrice Gasnier 
355*63f004e7SFabrice Gasnier 	if (!adc_vss_value(dev, &val))
356*63f004e7SFabrice Gasnier 		vref -= val;
357*63f004e7SFabrice Gasnier 
358*63f004e7SFabrice Gasnier 	ret = adc_data_mask(dev, &data_mask);
359*63f004e7SFabrice Gasnier 	if (ret)
360*63f004e7SFabrice Gasnier 		return ret;
361*63f004e7SFabrice Gasnier 
362*63f004e7SFabrice Gasnier 	raw64 *= vref;
363*63f004e7SFabrice Gasnier 	do_div(raw64, data_mask);
364*63f004e7SFabrice Gasnier 	*uV = raw64;
365*63f004e7SFabrice Gasnier 
366*63f004e7SFabrice Gasnier 	return 0;
367*63f004e7SFabrice Gasnier }
368*63f004e7SFabrice Gasnier 
adc_vdd_platdata_set(struct udevice * dev)3695decbf53SPrzemyslaw Marczak static int adc_vdd_platdata_set(struct udevice *dev)
3705decbf53SPrzemyslaw Marczak {
3715decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
37253d788d8SSimon Glass 	int ret;
3735decbf53SPrzemyslaw Marczak 	char *prop;
3745decbf53SPrzemyslaw Marczak 
3755decbf53SPrzemyslaw Marczak 	prop = "vdd-polarity-negative";
37653d788d8SSimon Glass 	uc_pdata->vdd_polarity_negative = dev_read_bool(dev, prop);
3775decbf53SPrzemyslaw Marczak 
378a4a87f7bSFabrice Gasnier 	/* Optionally get regulators */
379a4a87f7bSFabrice Gasnier 	ret = device_get_supply_regulator(dev, "vdd-supply",
380a4a87f7bSFabrice Gasnier 					  &uc_pdata->vdd_supply);
381a4a87f7bSFabrice Gasnier 	if (!ret)
382a4a87f7bSFabrice Gasnier 		return adc_vdd_platdata_update(dev);
383a4a87f7bSFabrice Gasnier 
3845decbf53SPrzemyslaw Marczak 	if (ret != -ENOENT)
3855decbf53SPrzemyslaw Marczak 		return ret;
3865decbf53SPrzemyslaw Marczak 
3875decbf53SPrzemyslaw Marczak 	/* No vdd-supply phandle. */
3885decbf53SPrzemyslaw Marczak 	prop  = "vdd-microvolts";
38953d788d8SSimon Glass 	uc_pdata->vdd_microvolts = dev_read_u32_default(dev, prop, -ENODATA);
3905decbf53SPrzemyslaw Marczak 
3915decbf53SPrzemyslaw Marczak 	return 0;
3925decbf53SPrzemyslaw Marczak }
3935decbf53SPrzemyslaw Marczak 
adc_vss_platdata_set(struct udevice * dev)3945decbf53SPrzemyslaw Marczak static int adc_vss_platdata_set(struct udevice *dev)
3955decbf53SPrzemyslaw Marczak {
3965decbf53SPrzemyslaw Marczak 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
39753d788d8SSimon Glass 	int ret;
3985decbf53SPrzemyslaw Marczak 	char *prop;
3995decbf53SPrzemyslaw Marczak 
4005decbf53SPrzemyslaw Marczak 	prop = "vss-polarity-negative";
40153d788d8SSimon Glass 	uc_pdata->vss_polarity_negative = dev_read_bool(dev, prop);
4025decbf53SPrzemyslaw Marczak 
403a4a87f7bSFabrice Gasnier 	ret = device_get_supply_regulator(dev, "vss-supply",
404a4a87f7bSFabrice Gasnier 					  &uc_pdata->vss_supply);
405a4a87f7bSFabrice Gasnier 	if (!ret)
406a4a87f7bSFabrice Gasnier 		return adc_vss_platdata_update(dev);
407a4a87f7bSFabrice Gasnier 
4085decbf53SPrzemyslaw Marczak 	if (ret != -ENOENT)
4095decbf53SPrzemyslaw Marczak 		return ret;
4105decbf53SPrzemyslaw Marczak 
4115decbf53SPrzemyslaw Marczak 	/* No vss-supply phandle. */
4125decbf53SPrzemyslaw Marczak 	prop = "vss-microvolts";
41353d788d8SSimon Glass 	uc_pdata->vss_microvolts = dev_read_u32_default(dev, prop, -ENODATA);
4145decbf53SPrzemyslaw Marczak 
4155decbf53SPrzemyslaw Marczak 	return 0;
4165decbf53SPrzemyslaw Marczak }
4175decbf53SPrzemyslaw Marczak 
adc_pre_probe(struct udevice * dev)4185decbf53SPrzemyslaw Marczak static int adc_pre_probe(struct udevice *dev)
4195decbf53SPrzemyslaw Marczak {
4205decbf53SPrzemyslaw Marczak 	int ret;
4215decbf53SPrzemyslaw Marczak 
4225decbf53SPrzemyslaw Marczak 	/* Set ADC VDD platdata: polarity, uV, regulator (phandle). */
4235decbf53SPrzemyslaw Marczak 	ret = adc_vdd_platdata_set(dev);
4245decbf53SPrzemyslaw Marczak 	if (ret)
4259b643e31SMasahiro Yamada 		pr_err("%s: Can't update Vdd. Error: %d", dev->name, ret);
4265decbf53SPrzemyslaw Marczak 
4275decbf53SPrzemyslaw Marczak 	/* Set ADC VSS platdata: polarity, uV, regulator (phandle). */
4285decbf53SPrzemyslaw Marczak 	ret = adc_vss_platdata_set(dev);
4295decbf53SPrzemyslaw Marczak 	if (ret)
4309b643e31SMasahiro Yamada 		pr_err("%s: Can't update Vss. Error: %d", dev->name, ret);
4315decbf53SPrzemyslaw Marczak 
4325decbf53SPrzemyslaw Marczak 	return 0;
4335decbf53SPrzemyslaw Marczak }
4345decbf53SPrzemyslaw Marczak 
4355decbf53SPrzemyslaw Marczak UCLASS_DRIVER(adc) = {
4365decbf53SPrzemyslaw Marczak 	.id	= UCLASS_ADC,
4375decbf53SPrzemyslaw Marczak 	.name	= "adc",
4385decbf53SPrzemyslaw Marczak 	.pre_probe =  adc_pre_probe,
4395decbf53SPrzemyslaw Marczak 	.per_device_platdata_auto_alloc_size = ADC_UCLASS_PLATDATA_SIZE,
4405decbf53SPrzemyslaw Marczak };
441