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