uboot/drivers/adc/adc-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2015 Samsung Electronics
   4 * Przemyslaw Marczak <p.marczak@samsung.com>
   5 */
   6
   7#include <common.h>
   8#include <errno.h>
   9#include <div64.h>
  10#include <dm.h>
  11#include <dm/lists.h>
  12#include <dm/device-internal.h>
  13#include <dm/uclass-internal.h>
  14#include <adc.h>
  15#include <linux/delay.h>
  16#include <power/regulator.h>
  17
  18#define ADC_UCLASS_PLATDATA_SIZE        sizeof(struct adc_uclass_platdata)
  19#define CHECK_NUMBER                    true
  20#define CHECK_MASK                      (!CHECK_NUMBER)
  21
  22/* TODO: add support for timer uclass (for early calls) */
  23#ifdef CONFIG_SANDBOX_ARCH
  24#define sdelay(x)       udelay(x)
  25#else
  26extern void sdelay(unsigned long loops);
  27#endif
  28
  29static int check_channel(struct udevice *dev, int value, bool number_or_mask,
  30                         const char *caller_function)
  31{
  32        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
  33        unsigned mask = number_or_mask ? (1 << value) : value;
  34
  35        /* For the real ADC hardware, some ADC channels can be inactive.
  36         * For example if device has 4 analog channels, and only channels
  37         * 1-st and 3-rd are valid, then channel mask is: 0b1010, so request
  38         * with mask 0b1110 should return an error.
  39        */
  40        if ((uc_pdata->channel_mask >= mask) && (uc_pdata->channel_mask & mask))
  41                return 0;
  42
  43        printf("Error in %s/%s().\nWrong channel selection for device: %s\n",
  44               __FILE__, caller_function, dev->name);
  45
  46        return -EINVAL;
  47}
  48
  49static int adc_supply_enable(struct udevice *dev)
  50{
  51        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
  52        const char *supply_type;
  53        int ret = 0;
  54
  55        if (uc_pdata->vdd_supply) {
  56                supply_type = "vdd";
  57                ret = regulator_set_enable(uc_pdata->vdd_supply, true);
  58        }
  59
  60        if (!ret && uc_pdata->vss_supply) {
  61                supply_type = "vss";
  62                ret = regulator_set_enable(uc_pdata->vss_supply, true);
  63        }
  64
  65        if (ret)
  66                pr_err("%s: can't enable %s-supply!", dev->name, supply_type);
  67
  68        return ret;
  69}
  70
  71int adc_data_mask(struct udevice *dev, unsigned int *data_mask)
  72{
  73        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
  74
  75        if (!uc_pdata)
  76                return -ENOSYS;
  77
  78        *data_mask = uc_pdata->data_mask;
  79        return 0;
  80}
  81
  82int adc_channel_mask(struct udevice *dev, unsigned int *channel_mask)
  83{
  84        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
  85
  86        if (!uc_pdata)
  87                return -ENOSYS;
  88
  89        *channel_mask = uc_pdata->channel_mask;
  90
  91        return 0;
  92}
  93
  94int adc_stop(struct udevice *dev)
  95{
  96        const struct adc_ops *ops = dev_get_driver_ops(dev);
  97
  98        if (!ops->stop)
  99                return -ENOSYS;
 100
 101        return ops->stop(dev);
 102}
 103
 104int adc_start_channel(struct udevice *dev, int channel)
 105{
 106        const struct adc_ops *ops = dev_get_driver_ops(dev);
 107        int ret;
 108
 109        if (!ops->start_channel)
 110                return -ENOSYS;
 111
 112        ret = check_channel(dev, channel, CHECK_NUMBER, __func__);
 113        if (ret)
 114                return ret;
 115
 116        ret = adc_supply_enable(dev);
 117        if (ret)
 118                return ret;
 119
 120        return ops->start_channel(dev, channel);
 121}
 122
 123int adc_start_channels(struct udevice *dev, unsigned int channel_mask)
 124{
 125        const struct adc_ops *ops = dev_get_driver_ops(dev);
 126        int ret;
 127
 128        if (!ops->start_channels)
 129                return -ENOSYS;
 130
 131        ret = check_channel(dev, channel_mask, CHECK_MASK, __func__);
 132        if (ret)
 133                return ret;
 134
 135        ret = adc_supply_enable(dev);
 136        if (ret)
 137                return ret;
 138
 139        return ops->start_channels(dev, channel_mask);
 140}
 141
 142int adc_channel_data(struct udevice *dev, int channel, unsigned int *data)
 143{
 144        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 145        const struct adc_ops *ops = dev_get_driver_ops(dev);
 146        unsigned int timeout_us = uc_pdata->data_timeout_us;
 147        int ret;
 148
 149        if (!ops->channel_data)
 150                return -ENOSYS;
 151
 152        ret = check_channel(dev, channel, CHECK_NUMBER, __func__);
 153        if (ret)
 154                return ret;
 155
 156        do {
 157                ret = ops->channel_data(dev, channel, data);
 158                if (!ret || ret != -EBUSY)
 159                        break;
 160
 161                /* TODO: use timer uclass (for early calls). */
 162                sdelay(5);
 163        } while (timeout_us--);
 164
 165        return ret;
 166}
 167
 168int adc_channels_data(struct udevice *dev, unsigned int channel_mask,
 169                      struct adc_channel *channels)
 170{
 171        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 172        unsigned int timeout_us = uc_pdata->multidata_timeout_us;
 173        const struct adc_ops *ops = dev_get_driver_ops(dev);
 174        int ret;
 175
 176        if (!ops->channels_data)
 177                return -ENOSYS;
 178
 179        ret = check_channel(dev, channel_mask, CHECK_MASK, __func__);
 180        if (ret)
 181                return ret;
 182
 183        do {
 184                ret = ops->channels_data(dev, channel_mask, channels);
 185                if (!ret || ret != -EBUSY)
 186                        break;
 187
 188                /* TODO: use timer uclass (for early calls). */
 189                sdelay(5);
 190        } while (timeout_us--);
 191
 192        return ret;
 193}
 194
 195int adc_channel_single_shot(const char *name, int channel, unsigned int *data)
 196{
 197        struct udevice *dev;
 198        int ret;
 199
 200        ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev);
 201        if (ret)
 202                return ret;
 203
 204        ret = adc_start_channel(dev, channel);
 205        if (ret)
 206                return ret;
 207
 208        ret = adc_channel_data(dev, channel, data);
 209        if (ret)
 210                return ret;
 211
 212        return 0;
 213}
 214
 215static int _adc_channels_single_shot(struct udevice *dev,
 216                                     unsigned int channel_mask,
 217                                     struct adc_channel *channels)
 218{
 219        unsigned int data;
 220        int channel, ret;
 221
 222        for (channel = 0; channel <= ADC_MAX_CHANNEL; channel++) {
 223                /* Check channel bit. */
 224                if (!((channel_mask >> channel) & 0x1))
 225                        continue;
 226
 227                ret = adc_start_channel(dev, channel);
 228                if (ret)
 229                        return ret;
 230
 231                ret = adc_channel_data(dev, channel, &data);
 232                if (ret)
 233                        return ret;
 234
 235                channels->id = channel;
 236                channels->data = data;
 237                channels++;
 238        }
 239
 240        return 0;
 241}
 242
 243int adc_channels_single_shot(const char *name, unsigned int channel_mask,
 244                             struct adc_channel *channels)
 245{
 246        struct udevice *dev;
 247        int ret;
 248
 249        ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev);
 250        if (ret)
 251                return ret;
 252
 253        ret = adc_start_channels(dev, channel_mask);
 254        if (ret)
 255                goto try_manual;
 256
 257        ret = adc_channels_data(dev, channel_mask, channels);
 258        if (ret)
 259                return ret;
 260
 261        return 0;
 262
 263try_manual:
 264        if (ret != -ENOSYS)
 265                return ret;
 266
 267        return _adc_channels_single_shot(dev, channel_mask, channels);
 268}
 269
 270static int adc_vdd_platdata_update(struct udevice *dev)
 271{
 272        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 273        int ret;
 274
 275        /* Warning!
 276         * This function can't return supply device before its bind.
 277         * Please pay attention to proper fdt scan sequence. If ADC device
 278         * will bind before its supply regulator device, then the below 'get'
 279         * will return an error.
 280         */
 281        if (!uc_pdata->vdd_supply)
 282                return 0;
 283
 284        ret = regulator_get_value(uc_pdata->vdd_supply);
 285        if (ret < 0)
 286                return ret;
 287
 288        uc_pdata->vdd_microvolts = ret;
 289
 290        return 0;
 291}
 292
 293static int adc_vss_platdata_update(struct udevice *dev)
 294{
 295        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 296        int ret;
 297
 298        if (!uc_pdata->vss_supply)
 299                return 0;
 300
 301        ret = regulator_get_value(uc_pdata->vss_supply);
 302        if (ret < 0)
 303                return ret;
 304
 305        uc_pdata->vss_microvolts = ret;
 306
 307        return 0;
 308}
 309
 310int adc_vdd_value(struct udevice *dev, int *uV)
 311{
 312        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 313        int ret, value_sign = uc_pdata->vdd_polarity_negative ? -1 : 1;
 314
 315        /* Update the regulator Value. */
 316        ret = adc_vdd_platdata_update(dev);
 317        if (ret)
 318                return ret;
 319
 320        if (uc_pdata->vdd_microvolts == -ENODATA)
 321                return -ENODATA;
 322
 323        *uV = uc_pdata->vdd_microvolts * value_sign;
 324
 325        return 0;
 326}
 327
 328int adc_vss_value(struct udevice *dev, int *uV)
 329{
 330        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 331        int ret, value_sign = uc_pdata->vss_polarity_negative ? -1 : 1;
 332
 333        /* Update the regulator Value. */
 334        ret = adc_vss_platdata_update(dev);
 335        if (ret)
 336                return ret;
 337
 338        if (uc_pdata->vss_microvolts == -ENODATA)
 339                return -ENODATA;
 340
 341        *uV = uc_pdata->vss_microvolts * value_sign;
 342
 343        return 0;
 344}
 345
 346int adc_raw_to_uV(struct udevice *dev, unsigned int raw, int *uV)
 347{
 348        unsigned int data_mask;
 349        int ret, val, vref;
 350        u64 raw64 = raw;
 351
 352        ret = adc_vdd_value(dev, &vref);
 353        if (ret)
 354                return ret;
 355
 356        if (!adc_vss_value(dev, &val))
 357                vref -= val;
 358
 359        ret = adc_data_mask(dev, &data_mask);
 360        if (ret)
 361                return ret;
 362
 363        raw64 *= vref;
 364        do_div(raw64, data_mask);
 365        *uV = raw64;
 366
 367        return 0;
 368}
 369
 370static int adc_vdd_platdata_set(struct udevice *dev)
 371{
 372        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 373        int ret;
 374        char *prop;
 375
 376        prop = "vdd-polarity-negative";
 377        uc_pdata->vdd_polarity_negative = dev_read_bool(dev, prop);
 378
 379        /* Optionally get regulators */
 380        ret = device_get_supply_regulator(dev, "vdd-supply",
 381                                          &uc_pdata->vdd_supply);
 382        if (!ret)
 383                return adc_vdd_platdata_update(dev);
 384
 385        if (ret != -ENOENT)
 386                return ret;
 387
 388        /* No vdd-supply phandle. */
 389        prop  = "vdd-microvolts";
 390        uc_pdata->vdd_microvolts = dev_read_u32_default(dev, prop, -ENODATA);
 391
 392        return 0;
 393}
 394
 395static int adc_vss_platdata_set(struct udevice *dev)
 396{
 397        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 398        int ret;
 399        char *prop;
 400
 401        prop = "vss-polarity-negative";
 402        uc_pdata->vss_polarity_negative = dev_read_bool(dev, prop);
 403
 404        ret = device_get_supply_regulator(dev, "vss-supply",
 405                                          &uc_pdata->vss_supply);
 406        if (!ret)
 407                return adc_vss_platdata_update(dev);
 408
 409        if (ret != -ENOENT)
 410                return ret;
 411
 412        /* No vss-supply phandle. */
 413        prop = "vss-microvolts";
 414        uc_pdata->vss_microvolts = dev_read_u32_default(dev, prop, -ENODATA);
 415
 416        return 0;
 417}
 418
 419static int adc_pre_probe(struct udevice *dev)
 420{
 421        int ret;
 422
 423        /* Set ADC VDD platdata: polarity, uV, regulator (phandle). */
 424        ret = adc_vdd_platdata_set(dev);
 425        if (ret)
 426                pr_err("%s: Can't update Vdd. Error: %d", dev->name, ret);
 427
 428        /* Set ADC VSS platdata: polarity, uV, regulator (phandle). */
 429        ret = adc_vss_platdata_set(dev);
 430        if (ret)
 431                pr_err("%s: Can't update Vss. Error: %d", dev->name, ret);
 432
 433        return 0;
 434}
 435
 436UCLASS_DRIVER(adc) = {
 437        .id     = UCLASS_ADC,
 438        .name   = "adc",
 439        .pre_probe =  adc_pre_probe,
 440        .per_device_platdata_auto_alloc_size = ADC_UCLASS_PLATDATA_SIZE,
 441};
 442