15decbf53SPrzemyslaw Marczak /*
25decbf53SPrzemyslaw Marczak * Copyright (C) 2015 Samsung Electronics
35decbf53SPrzemyslaw Marczak * Przemyslaw Marczak <p.marczak@samsung.com>
45decbf53SPrzemyslaw Marczak *
55decbf53SPrzemyslaw Marczak * SPDX-License-Identifier: GPL-2.0+
65decbf53SPrzemyslaw Marczak */
75decbf53SPrzemyslaw Marczak
85decbf53SPrzemyslaw Marczak #include <common.h>
95decbf53SPrzemyslaw Marczak #include <errno.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 DECLARE_GLOBAL_DATA_PTR;
185decbf53SPrzemyslaw Marczak
195decbf53SPrzemyslaw Marczak #define ADC_UCLASS_PLATDATA_SIZE sizeof(struct adc_uclass_platdata)
205decbf53SPrzemyslaw Marczak #define CHECK_NUMBER true
215decbf53SPrzemyslaw Marczak #define CHECK_MASK (!CHECK_NUMBER)
225decbf53SPrzemyslaw Marczak
235decbf53SPrzemyslaw Marczak /* TODO: add support for timer uclass (for early calls) */
245decbf53SPrzemyslaw Marczak #ifdef CONFIG_SANDBOX_ARCH
255decbf53SPrzemyslaw Marczak #define sdelay(x) udelay(x)
265decbf53SPrzemyslaw Marczak #else
275decbf53SPrzemyslaw Marczak extern void sdelay(unsigned long loops);
285decbf53SPrzemyslaw Marczak #endif
295decbf53SPrzemyslaw Marczak
check_channel(struct udevice * dev,int value,bool number_or_mask,const char * caller_function)305decbf53SPrzemyslaw Marczak static int check_channel(struct udevice *dev, int value, bool number_or_mask,
315decbf53SPrzemyslaw Marczak const char *caller_function)
325decbf53SPrzemyslaw Marczak {
335decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
345decbf53SPrzemyslaw Marczak unsigned mask = number_or_mask ? (1 << value) : value;
355decbf53SPrzemyslaw Marczak
365decbf53SPrzemyslaw Marczak /* For the real ADC hardware, some ADC channels can be inactive.
375decbf53SPrzemyslaw Marczak * For example if device has 4 analog channels, and only channels
385decbf53SPrzemyslaw Marczak * 1-st and 3-rd are valid, then channel mask is: 0b1010, so request
395decbf53SPrzemyslaw Marczak * with mask 0b1110 should return an error.
405decbf53SPrzemyslaw Marczak */
415decbf53SPrzemyslaw Marczak if ((uc_pdata->channel_mask >= mask) && (uc_pdata->channel_mask & mask))
425decbf53SPrzemyslaw Marczak return 0;
435decbf53SPrzemyslaw Marczak
445decbf53SPrzemyslaw Marczak printf("Error in %s/%s().\nWrong channel selection for device: %s\n",
455decbf53SPrzemyslaw Marczak __FILE__, caller_function, dev->name);
465decbf53SPrzemyslaw Marczak
475decbf53SPrzemyslaw Marczak return -EINVAL;
485decbf53SPrzemyslaw Marczak }
495decbf53SPrzemyslaw Marczak
50*35ef9ac3SJoseph Chen #ifdef CONFIG_ADC_REQ_REGULATOR
adc_supply_enable(struct udevice * dev)515decbf53SPrzemyslaw Marczak static int adc_supply_enable(struct udevice *dev)
525decbf53SPrzemyslaw Marczak {
535decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
545decbf53SPrzemyslaw Marczak const char *supply_type;
555decbf53SPrzemyslaw Marczak int ret = 0;
565decbf53SPrzemyslaw Marczak
575decbf53SPrzemyslaw Marczak if (uc_pdata->vdd_supply) {
585decbf53SPrzemyslaw Marczak supply_type = "vdd";
595decbf53SPrzemyslaw Marczak ret = regulator_set_enable(uc_pdata->vdd_supply, true);
605decbf53SPrzemyslaw Marczak }
615decbf53SPrzemyslaw Marczak
625decbf53SPrzemyslaw Marczak if (!ret && uc_pdata->vss_supply) {
635decbf53SPrzemyslaw Marczak supply_type = "vss";
645decbf53SPrzemyslaw Marczak ret = regulator_set_enable(uc_pdata->vss_supply, true);
655decbf53SPrzemyslaw Marczak }
665decbf53SPrzemyslaw Marczak
675decbf53SPrzemyslaw Marczak if (ret)
6890aa625cSMasahiro Yamada pr_err("%s: can't enable %s-supply!", dev->name, supply_type);
695decbf53SPrzemyslaw Marczak
705decbf53SPrzemyslaw Marczak return ret;
715decbf53SPrzemyslaw Marczak }
72*35ef9ac3SJoseph Chen #else
adc_supply_enable(struct udevice * dev)73*35ef9ac3SJoseph Chen static inline int adc_supply_enable(struct udevice *dev) { return 0; }
74*35ef9ac3SJoseph Chen #endif
755decbf53SPrzemyslaw Marczak
adc_data_mask(struct udevice * dev,unsigned int * data_mask)765decbf53SPrzemyslaw Marczak int adc_data_mask(struct udevice *dev, unsigned int *data_mask)
775decbf53SPrzemyslaw Marczak {
785decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
795decbf53SPrzemyslaw Marczak
805decbf53SPrzemyslaw Marczak if (!uc_pdata)
815decbf53SPrzemyslaw Marczak return -ENOSYS;
825decbf53SPrzemyslaw Marczak
835decbf53SPrzemyslaw Marczak *data_mask = uc_pdata->data_mask;
845decbf53SPrzemyslaw Marczak return 0;
855decbf53SPrzemyslaw Marczak }
865decbf53SPrzemyslaw Marczak
adc_stop(struct udevice * dev)875decbf53SPrzemyslaw Marczak int adc_stop(struct udevice *dev)
885decbf53SPrzemyslaw Marczak {
895decbf53SPrzemyslaw Marczak const struct adc_ops *ops = dev_get_driver_ops(dev);
905decbf53SPrzemyslaw Marczak
915decbf53SPrzemyslaw Marczak if (!ops->stop)
925decbf53SPrzemyslaw Marczak return -ENOSYS;
935decbf53SPrzemyslaw Marczak
945decbf53SPrzemyslaw Marczak return ops->stop(dev);
955decbf53SPrzemyslaw Marczak }
965decbf53SPrzemyslaw Marczak
adc_start_channel(struct udevice * dev,int channel)975decbf53SPrzemyslaw Marczak int adc_start_channel(struct udevice *dev, int channel)
985decbf53SPrzemyslaw Marczak {
995decbf53SPrzemyslaw Marczak const struct adc_ops *ops = dev_get_driver_ops(dev);
1005decbf53SPrzemyslaw Marczak int ret;
1015decbf53SPrzemyslaw Marczak
1025decbf53SPrzemyslaw Marczak if (!ops->start_channel)
1035decbf53SPrzemyslaw Marczak return -ENOSYS;
1045decbf53SPrzemyslaw Marczak
1055decbf53SPrzemyslaw Marczak ret = check_channel(dev, channel, CHECK_NUMBER, __func__);
1065decbf53SPrzemyslaw Marczak if (ret)
1075decbf53SPrzemyslaw Marczak return ret;
1085decbf53SPrzemyslaw Marczak
1095decbf53SPrzemyslaw Marczak ret = adc_supply_enable(dev);
1105decbf53SPrzemyslaw Marczak if (ret)
1115decbf53SPrzemyslaw Marczak return ret;
1125decbf53SPrzemyslaw Marczak
1135decbf53SPrzemyslaw Marczak return ops->start_channel(dev, channel);
1145decbf53SPrzemyslaw Marczak }
1155decbf53SPrzemyslaw Marczak
adc_start_channels(struct udevice * dev,unsigned int channel_mask)1165decbf53SPrzemyslaw Marczak int adc_start_channels(struct udevice *dev, unsigned int channel_mask)
1175decbf53SPrzemyslaw Marczak {
1185decbf53SPrzemyslaw Marczak const struct adc_ops *ops = dev_get_driver_ops(dev);
1195decbf53SPrzemyslaw Marczak int ret;
1205decbf53SPrzemyslaw Marczak
1215decbf53SPrzemyslaw Marczak if (!ops->start_channels)
1225decbf53SPrzemyslaw Marczak return -ENOSYS;
1235decbf53SPrzemyslaw Marczak
1245decbf53SPrzemyslaw Marczak ret = check_channel(dev, channel_mask, CHECK_MASK, __func__);
1255decbf53SPrzemyslaw Marczak if (ret)
1265decbf53SPrzemyslaw Marczak return ret;
1275decbf53SPrzemyslaw Marczak
1285decbf53SPrzemyslaw Marczak ret = adc_supply_enable(dev);
1295decbf53SPrzemyslaw Marczak if (ret)
1305decbf53SPrzemyslaw Marczak return ret;
1315decbf53SPrzemyslaw Marczak
1325decbf53SPrzemyslaw Marczak return ops->start_channels(dev, channel_mask);
1335decbf53SPrzemyslaw Marczak }
1345decbf53SPrzemyslaw Marczak
adc_channel_data(struct udevice * dev,int channel,unsigned int * data)1355decbf53SPrzemyslaw Marczak int adc_channel_data(struct udevice *dev, int channel, unsigned int *data)
1365decbf53SPrzemyslaw Marczak {
1375decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
1385decbf53SPrzemyslaw Marczak const struct adc_ops *ops = dev_get_driver_ops(dev);
1395decbf53SPrzemyslaw Marczak unsigned int timeout_us = uc_pdata->data_timeout_us;
1405decbf53SPrzemyslaw Marczak int ret;
1415decbf53SPrzemyslaw Marczak
1425decbf53SPrzemyslaw Marczak if (!ops->channel_data)
1435decbf53SPrzemyslaw Marczak return -ENOSYS;
1445decbf53SPrzemyslaw Marczak
1455decbf53SPrzemyslaw Marczak ret = check_channel(dev, channel, CHECK_NUMBER, __func__);
1465decbf53SPrzemyslaw Marczak if (ret)
1475decbf53SPrzemyslaw Marczak return ret;
1485decbf53SPrzemyslaw Marczak
1495decbf53SPrzemyslaw Marczak do {
1505decbf53SPrzemyslaw Marczak ret = ops->channel_data(dev, channel, data);
1515decbf53SPrzemyslaw Marczak if (!ret || ret != -EBUSY)
1525decbf53SPrzemyslaw Marczak break;
1535decbf53SPrzemyslaw Marczak
1545decbf53SPrzemyslaw Marczak /* TODO: use timer uclass (for early calls). */
1555decbf53SPrzemyslaw Marczak sdelay(5);
1565decbf53SPrzemyslaw Marczak } while (timeout_us--);
1575decbf53SPrzemyslaw Marczak
1585decbf53SPrzemyslaw Marczak return ret;
1595decbf53SPrzemyslaw Marczak }
1605decbf53SPrzemyslaw Marczak
adc_channels_data(struct udevice * dev,unsigned int channel_mask,struct adc_channel * channels)1615decbf53SPrzemyslaw Marczak int adc_channels_data(struct udevice *dev, unsigned int channel_mask,
1625decbf53SPrzemyslaw Marczak struct adc_channel *channels)
1635decbf53SPrzemyslaw Marczak {
1645decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
1655decbf53SPrzemyslaw Marczak unsigned int timeout_us = uc_pdata->multidata_timeout_us;
1665decbf53SPrzemyslaw Marczak const struct adc_ops *ops = dev_get_driver_ops(dev);
1675decbf53SPrzemyslaw Marczak int ret;
1685decbf53SPrzemyslaw Marczak
1695decbf53SPrzemyslaw Marczak if (!ops->channels_data)
1705decbf53SPrzemyslaw Marczak return -ENOSYS;
1715decbf53SPrzemyslaw Marczak
1725decbf53SPrzemyslaw Marczak ret = check_channel(dev, channel_mask, CHECK_MASK, __func__);
1735decbf53SPrzemyslaw Marczak if (ret)
1745decbf53SPrzemyslaw Marczak return ret;
1755decbf53SPrzemyslaw Marczak
1765decbf53SPrzemyslaw Marczak do {
1775decbf53SPrzemyslaw Marczak ret = ops->channels_data(dev, channel_mask, channels);
1785decbf53SPrzemyslaw Marczak if (!ret || ret != -EBUSY)
1795decbf53SPrzemyslaw Marczak break;
1805decbf53SPrzemyslaw Marczak
1815decbf53SPrzemyslaw Marczak /* TODO: use timer uclass (for early calls). */
1825decbf53SPrzemyslaw Marczak sdelay(5);
1835decbf53SPrzemyslaw Marczak } while (timeout_us--);
1845decbf53SPrzemyslaw Marczak
1855decbf53SPrzemyslaw Marczak return ret;
1865decbf53SPrzemyslaw Marczak }
1875decbf53SPrzemyslaw Marczak
adc_channel_single_shot(const char * name,int channel,unsigned int * data)1885decbf53SPrzemyslaw Marczak int adc_channel_single_shot(const char *name, int channel, unsigned int *data)
1895decbf53SPrzemyslaw Marczak {
1905decbf53SPrzemyslaw Marczak struct udevice *dev;
1915decbf53SPrzemyslaw Marczak int ret;
1925decbf53SPrzemyslaw Marczak
1935decbf53SPrzemyslaw Marczak ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev);
1945decbf53SPrzemyslaw Marczak if (ret)
1955decbf53SPrzemyslaw Marczak return ret;
1965decbf53SPrzemyslaw Marczak
1975decbf53SPrzemyslaw Marczak ret = adc_start_channel(dev, channel);
1985decbf53SPrzemyslaw Marczak if (ret)
1995decbf53SPrzemyslaw Marczak return ret;
2005decbf53SPrzemyslaw Marczak
2015decbf53SPrzemyslaw Marczak ret = adc_channel_data(dev, channel, data);
2025decbf53SPrzemyslaw Marczak if (ret)
2035decbf53SPrzemyslaw Marczak return ret;
2045decbf53SPrzemyslaw Marczak
2055decbf53SPrzemyslaw Marczak return 0;
2065decbf53SPrzemyslaw Marczak }
2075decbf53SPrzemyslaw Marczak
_adc_channels_single_shot(struct udevice * dev,unsigned int channel_mask,struct adc_channel * channels)2085decbf53SPrzemyslaw Marczak static int _adc_channels_single_shot(struct udevice *dev,
2095decbf53SPrzemyslaw Marczak unsigned int channel_mask,
2105decbf53SPrzemyslaw Marczak struct adc_channel *channels)
2115decbf53SPrzemyslaw Marczak {
2125decbf53SPrzemyslaw Marczak unsigned int data;
2135decbf53SPrzemyslaw Marczak int channel, ret;
2145decbf53SPrzemyslaw Marczak
2155decbf53SPrzemyslaw Marczak for (channel = 0; channel <= ADC_MAX_CHANNEL; channel++) {
2165decbf53SPrzemyslaw Marczak /* Check channel bit. */
2175decbf53SPrzemyslaw Marczak if (!((channel_mask >> channel) & 0x1))
2185decbf53SPrzemyslaw Marczak continue;
2195decbf53SPrzemyslaw Marczak
2205decbf53SPrzemyslaw Marczak ret = adc_start_channel(dev, channel);
2215decbf53SPrzemyslaw Marczak if (ret)
2225decbf53SPrzemyslaw Marczak return ret;
2235decbf53SPrzemyslaw Marczak
2245decbf53SPrzemyslaw Marczak ret = adc_channel_data(dev, channel, &data);
2255decbf53SPrzemyslaw Marczak if (ret)
2265decbf53SPrzemyslaw Marczak return ret;
2275decbf53SPrzemyslaw Marczak
2285decbf53SPrzemyslaw Marczak channels->id = channel;
2295decbf53SPrzemyslaw Marczak channels->data = data;
2305decbf53SPrzemyslaw Marczak channels++;
2315decbf53SPrzemyslaw Marczak }
2325decbf53SPrzemyslaw Marczak
2335decbf53SPrzemyslaw Marczak return 0;
2345decbf53SPrzemyslaw Marczak }
2355decbf53SPrzemyslaw Marczak
adc_channels_single_shot(const char * name,unsigned int channel_mask,struct adc_channel * channels)2365decbf53SPrzemyslaw Marczak int adc_channels_single_shot(const char *name, unsigned int channel_mask,
2375decbf53SPrzemyslaw Marczak struct adc_channel *channels)
2385decbf53SPrzemyslaw Marczak {
2395decbf53SPrzemyslaw Marczak struct udevice *dev;
2405decbf53SPrzemyslaw Marczak int ret;
2415decbf53SPrzemyslaw Marczak
2425decbf53SPrzemyslaw Marczak ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev);
2435decbf53SPrzemyslaw Marczak if (ret)
2445decbf53SPrzemyslaw Marczak return ret;
2455decbf53SPrzemyslaw Marczak
2465decbf53SPrzemyslaw Marczak ret = adc_start_channels(dev, channel_mask);
2475decbf53SPrzemyslaw Marczak if (ret)
2485decbf53SPrzemyslaw Marczak goto try_manual;
2495decbf53SPrzemyslaw Marczak
2505decbf53SPrzemyslaw Marczak ret = adc_channels_data(dev, channel_mask, channels);
2515decbf53SPrzemyslaw Marczak if (ret)
2525decbf53SPrzemyslaw Marczak return ret;
2535decbf53SPrzemyslaw Marczak
2545decbf53SPrzemyslaw Marczak return 0;
2555decbf53SPrzemyslaw Marczak
2565decbf53SPrzemyslaw Marczak try_manual:
2575decbf53SPrzemyslaw Marczak if (ret != -ENOSYS)
2585decbf53SPrzemyslaw Marczak return ret;
2595decbf53SPrzemyslaw Marczak
2605decbf53SPrzemyslaw Marczak return _adc_channels_single_shot(dev, channel_mask, channels);
2615decbf53SPrzemyslaw Marczak }
2625decbf53SPrzemyslaw Marczak
263*35ef9ac3SJoseph Chen #ifdef CONFIG_ADC_REQ_REGULATOR
adc_vdd_platdata_update(struct udevice * dev)2645decbf53SPrzemyslaw Marczak static int adc_vdd_platdata_update(struct udevice *dev)
2655decbf53SPrzemyslaw Marczak {
2665decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
2675decbf53SPrzemyslaw Marczak int ret;
2685decbf53SPrzemyslaw Marczak
2695decbf53SPrzemyslaw Marczak /* Warning!
2705decbf53SPrzemyslaw Marczak * This function can't return supply device before its bind.
2715decbf53SPrzemyslaw Marczak * Please pay attention to proper fdt scan sequence. If ADC device
2725decbf53SPrzemyslaw Marczak * will bind before its supply regulator device, then the below 'get'
2735decbf53SPrzemyslaw Marczak * will return an error.
2745decbf53SPrzemyslaw Marczak */
2755decbf53SPrzemyslaw Marczak ret = device_get_supply_regulator(dev, "vdd-supply",
2765decbf53SPrzemyslaw Marczak &uc_pdata->vdd_supply);
2775decbf53SPrzemyslaw Marczak if (ret)
2785decbf53SPrzemyslaw Marczak return ret;
2795decbf53SPrzemyslaw Marczak
2805decbf53SPrzemyslaw Marczak ret = regulator_get_value(uc_pdata->vdd_supply);
2815decbf53SPrzemyslaw Marczak if (ret < 0)
2825decbf53SPrzemyslaw Marczak return ret;
2835decbf53SPrzemyslaw Marczak
2845decbf53SPrzemyslaw Marczak uc_pdata->vdd_microvolts = ret;
2855decbf53SPrzemyslaw Marczak
2865decbf53SPrzemyslaw Marczak return 0;
2875decbf53SPrzemyslaw Marczak }
288*35ef9ac3SJoseph Chen #else
adc_vdd_platdata_update(struct udevice * dev)289*35ef9ac3SJoseph Chen static inline int adc_vdd_platdata_update(struct udevice *dev) { return 0; }
290*35ef9ac3SJoseph Chen #endif
2915decbf53SPrzemyslaw Marczak
292*35ef9ac3SJoseph Chen #ifdef CONFIG_ADC_REQ_REGULATOR
adc_vss_platdata_update(struct udevice * dev)2935decbf53SPrzemyslaw Marczak static int adc_vss_platdata_update(struct udevice *dev)
2945decbf53SPrzemyslaw Marczak {
2955decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
2965decbf53SPrzemyslaw Marczak int ret;
2975decbf53SPrzemyslaw Marczak
2985decbf53SPrzemyslaw Marczak ret = device_get_supply_regulator(dev, "vss-supply",
2995decbf53SPrzemyslaw Marczak &uc_pdata->vss_supply);
3005decbf53SPrzemyslaw Marczak if (ret)
3015decbf53SPrzemyslaw Marczak return ret;
3025decbf53SPrzemyslaw Marczak
3035decbf53SPrzemyslaw Marczak ret = regulator_get_value(uc_pdata->vss_supply);
3045decbf53SPrzemyslaw Marczak if (ret < 0)
3055decbf53SPrzemyslaw Marczak return ret;
3065decbf53SPrzemyslaw Marczak
3075decbf53SPrzemyslaw Marczak uc_pdata->vss_microvolts = ret;
3085decbf53SPrzemyslaw Marczak
3095decbf53SPrzemyslaw Marczak return 0;
3105decbf53SPrzemyslaw Marczak }
311*35ef9ac3SJoseph Chen #else
adc_vss_platdata_update(struct udevice * dev)312*35ef9ac3SJoseph Chen static inline int adc_vss_platdata_update(struct udevice *dev) { return 0; }
313*35ef9ac3SJoseph Chen #endif
3145decbf53SPrzemyslaw Marczak
adc_vdd_value(struct udevice * dev,int * uV)3155decbf53SPrzemyslaw Marczak int adc_vdd_value(struct udevice *dev, int *uV)
3165decbf53SPrzemyslaw Marczak {
3175decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
3185decbf53SPrzemyslaw Marczak int ret, value_sign = uc_pdata->vdd_polarity_negative ? -1 : 1;
3195decbf53SPrzemyslaw Marczak
3205decbf53SPrzemyslaw Marczak if (!uc_pdata->vdd_supply)
3215decbf53SPrzemyslaw Marczak goto nodev;
3225decbf53SPrzemyslaw Marczak
3235decbf53SPrzemyslaw Marczak /* Update the regulator Value. */
3245decbf53SPrzemyslaw Marczak ret = adc_vdd_platdata_update(dev);
3255decbf53SPrzemyslaw Marczak if (ret)
3265decbf53SPrzemyslaw Marczak return ret;
3275decbf53SPrzemyslaw Marczak nodev:
3285decbf53SPrzemyslaw Marczak if (uc_pdata->vdd_microvolts == -ENODATA)
3295decbf53SPrzemyslaw Marczak return -ENODATA;
3305decbf53SPrzemyslaw Marczak
3315decbf53SPrzemyslaw Marczak *uV = uc_pdata->vdd_microvolts * value_sign;
3325decbf53SPrzemyslaw Marczak
3335decbf53SPrzemyslaw Marczak return 0;
3345decbf53SPrzemyslaw Marczak }
3355decbf53SPrzemyslaw Marczak
adc_vss_value(struct udevice * dev,int * uV)3365decbf53SPrzemyslaw Marczak int adc_vss_value(struct udevice *dev, int *uV)
3375decbf53SPrzemyslaw Marczak {
3385decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
3395decbf53SPrzemyslaw Marczak int ret, value_sign = uc_pdata->vss_polarity_negative ? -1 : 1;
3405decbf53SPrzemyslaw Marczak
3415decbf53SPrzemyslaw Marczak if (!uc_pdata->vss_supply)
3425decbf53SPrzemyslaw Marczak goto nodev;
3435decbf53SPrzemyslaw Marczak
3445decbf53SPrzemyslaw Marczak /* Update the regulator Value. */
3455decbf53SPrzemyslaw Marczak ret = adc_vss_platdata_update(dev);
3465decbf53SPrzemyslaw Marczak if (ret)
3475decbf53SPrzemyslaw Marczak return ret;
3485decbf53SPrzemyslaw Marczak nodev:
3495decbf53SPrzemyslaw Marczak if (uc_pdata->vss_microvolts == -ENODATA)
3505decbf53SPrzemyslaw Marczak return -ENODATA;
3515decbf53SPrzemyslaw Marczak
3525decbf53SPrzemyslaw Marczak *uV = uc_pdata->vss_microvolts * value_sign;
3535decbf53SPrzemyslaw Marczak
3545decbf53SPrzemyslaw Marczak return 0;
3555decbf53SPrzemyslaw Marczak }
3565decbf53SPrzemyslaw Marczak
adc_vdd_platdata_set(struct udevice * dev)3575decbf53SPrzemyslaw Marczak static int adc_vdd_platdata_set(struct udevice *dev)
3585decbf53SPrzemyslaw Marczak {
3595decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
36053d788d8SSimon Glass int ret;
3615decbf53SPrzemyslaw Marczak char *prop;
3625decbf53SPrzemyslaw Marczak
3635decbf53SPrzemyslaw Marczak prop = "vdd-polarity-negative";
36453d788d8SSimon Glass uc_pdata->vdd_polarity_negative = dev_read_bool(dev, prop);
3655decbf53SPrzemyslaw Marczak
3665decbf53SPrzemyslaw Marczak ret = adc_vdd_platdata_update(dev);
3675decbf53SPrzemyslaw Marczak if (ret != -ENOENT)
3685decbf53SPrzemyslaw Marczak return ret;
3695decbf53SPrzemyslaw Marczak
3705decbf53SPrzemyslaw Marczak /* No vdd-supply phandle. */
3715decbf53SPrzemyslaw Marczak prop = "vdd-microvolts";
37253d788d8SSimon Glass uc_pdata->vdd_microvolts = dev_read_u32_default(dev, prop, -ENODATA);
3735decbf53SPrzemyslaw Marczak
3745decbf53SPrzemyslaw Marczak return 0;
3755decbf53SPrzemyslaw Marczak }
3765decbf53SPrzemyslaw Marczak
adc_vss_platdata_set(struct udevice * dev)3775decbf53SPrzemyslaw Marczak static int adc_vss_platdata_set(struct udevice *dev)
3785decbf53SPrzemyslaw Marczak {
3795decbf53SPrzemyslaw Marczak struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
38053d788d8SSimon Glass int ret;
3815decbf53SPrzemyslaw Marczak char *prop;
3825decbf53SPrzemyslaw Marczak
3835decbf53SPrzemyslaw Marczak prop = "vss-polarity-negative";
38453d788d8SSimon Glass uc_pdata->vss_polarity_negative = dev_read_bool(dev, prop);
3855decbf53SPrzemyslaw Marczak
3865decbf53SPrzemyslaw Marczak ret = adc_vss_platdata_update(dev);
3875decbf53SPrzemyslaw Marczak if (ret != -ENOENT)
3885decbf53SPrzemyslaw Marczak return ret;
3895decbf53SPrzemyslaw Marczak
3905decbf53SPrzemyslaw Marczak /* No vss-supply phandle. */
3915decbf53SPrzemyslaw Marczak prop = "vss-microvolts";
39253d788d8SSimon Glass uc_pdata->vss_microvolts = dev_read_u32_default(dev, prop, -ENODATA);
3935decbf53SPrzemyslaw Marczak
3945decbf53SPrzemyslaw Marczak return 0;
3955decbf53SPrzemyslaw Marczak }
3965decbf53SPrzemyslaw Marczak
adc_pre_probe(struct udevice * dev)3975decbf53SPrzemyslaw Marczak static int adc_pre_probe(struct udevice *dev)
3985decbf53SPrzemyslaw Marczak {
3995decbf53SPrzemyslaw Marczak int ret;
4005decbf53SPrzemyslaw Marczak
4015decbf53SPrzemyslaw Marczak /* Set ADC VDD platdata: polarity, uV, regulator (phandle). */
4025decbf53SPrzemyslaw Marczak ret = adc_vdd_platdata_set(dev);
4035decbf53SPrzemyslaw Marczak if (ret)
40490aa625cSMasahiro Yamada pr_err("%s: Can't update Vdd. Error: %d", dev->name, ret);
4055decbf53SPrzemyslaw Marczak
4065decbf53SPrzemyslaw Marczak /* Set ADC VSS platdata: polarity, uV, regulator (phandle). */
4075decbf53SPrzemyslaw Marczak ret = adc_vss_platdata_set(dev);
4085decbf53SPrzemyslaw Marczak if (ret)
40990aa625cSMasahiro Yamada pr_err("%s: Can't update Vss. Error: %d", dev->name, ret);
4105decbf53SPrzemyslaw Marczak
4115decbf53SPrzemyslaw Marczak return 0;
4125decbf53SPrzemyslaw Marczak }
4135decbf53SPrzemyslaw Marczak
4145decbf53SPrzemyslaw Marczak UCLASS_DRIVER(adc) = {
4155decbf53SPrzemyslaw Marczak .id = UCLASS_ADC,
4165decbf53SPrzemyslaw Marczak .name = "adc",
4175decbf53SPrzemyslaw Marczak .pre_probe = adc_pre_probe,
4185decbf53SPrzemyslaw Marczak .per_device_platdata_auto_alloc_size = ADC_UCLASS_PLATDATA_SIZE,
4195decbf53SPrzemyslaw Marczak };
420