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