sandbox.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * Copyright (C) 2015 Samsung Electronics
  3. * Przemyslaw Marczak <p.marczak@samsung.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <errno.h>
  9. #include <dm.h>
  10. #include <adc.h>
  11. #include <sandbox-adc.h>
  12. /**
  13. * struct sandbox_adc_priv - sandbox ADC device's operation status and data
  14. *
  15. * @conversion_status - conversion status: ACTIVE (started) / INACTIVE (stopped)
  16. * @conversion_mode - conversion mode: single or multi-channel
  17. * @active_channel - active channel number, valid for single channel mode
  18. * data[] - channels data
  19. */
  20. struct sandbox_adc_priv {
  21. int conversion_status;
  22. int conversion_mode;
  23. int active_channel_mask;
  24. unsigned int data[4];
  25. };
  26. int sandbox_adc_start_channel(struct udevice *dev, int channel)
  27. {
  28. struct sandbox_adc_priv *priv = dev_get_priv(dev);
  29. /* Set single-channel mode */
  30. priv->conversion_mode = SANDBOX_ADC_MODE_SINGLE_CHANNEL;
  31. /* Select channel */
  32. priv->active_channel_mask = 1 << channel;
  33. /* Start conversion */
  34. priv->conversion_status = SANDBOX_ADC_ACTIVE;
  35. return 0;
  36. }
  37. int sandbox_adc_start_channels(struct udevice *dev, unsigned int channel_mask)
  38. {
  39. struct sandbox_adc_priv *priv = dev_get_priv(dev);
  40. /* Set single-channel mode */
  41. priv->conversion_mode = SANDBOX_ADC_MODE_MULTI_CHANNEL;
  42. /* Select channel */
  43. priv->active_channel_mask = channel_mask;
  44. /* Start conversion */
  45. priv->conversion_status = SANDBOX_ADC_ACTIVE;
  46. return 0;
  47. }
  48. int sandbox_adc_channel_data(struct udevice *dev, int channel,
  49. unsigned int *data)
  50. {
  51. struct sandbox_adc_priv *priv = dev_get_priv(dev);
  52. /* For single-channel conversion mode, check if channel was selected */
  53. if ((priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) &&
  54. !(priv->active_channel_mask & (1 << channel))) {
  55. error("Request for an inactive channel!");
  56. return -EINVAL;
  57. }
  58. /* The conversion must be started before reading the data */
  59. if (priv->conversion_status == SANDBOX_ADC_INACTIVE)
  60. return -EIO;
  61. *data = priv->data[channel];
  62. return 0;
  63. }
  64. int sandbox_adc_channels_data(struct udevice *dev, unsigned int channel_mask,
  65. struct adc_channel *channels)
  66. {
  67. struct sandbox_adc_priv *priv = dev_get_priv(dev);
  68. int i;
  69. /* Return error for single-channel conversion mode */
  70. if (priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) {
  71. error("ADC in single-channel mode!");
  72. return -EPERM;
  73. }
  74. /* Check channel selection */
  75. if (!(priv->active_channel_mask & channel_mask)) {
  76. error("Request for an inactive channel!");
  77. return -EINVAL;
  78. }
  79. /* The conversion must be started before reading the data */
  80. if (priv->conversion_status == SANDBOX_ADC_INACTIVE)
  81. return -EIO;
  82. for (i = 0; i < SANDBOX_ADC_CHANNELS; i++) {
  83. if (!((channel_mask >> i) & 0x1))
  84. continue;
  85. channels->data = priv->data[i];
  86. channels->id = i;
  87. channels++;
  88. }
  89. return 0;
  90. }
  91. int sandbox_adc_stop(struct udevice *dev)
  92. {
  93. struct sandbox_adc_priv *priv = dev_get_priv(dev);
  94. /* Start conversion */
  95. priv->conversion_status = SANDBOX_ADC_INACTIVE;
  96. return 0;
  97. }
  98. int sandbox_adc_probe(struct udevice *dev)
  99. {
  100. struct sandbox_adc_priv *priv = dev_get_priv(dev);
  101. /* Stop conversion */
  102. priv->conversion_status = SANDBOX_ADC_INACTIVE;
  103. /* Set single-channel mode */
  104. priv->conversion_mode = SANDBOX_ADC_MODE_SINGLE_CHANNEL;
  105. /* Deselect all channels */
  106. priv->active_channel_mask = 0;
  107. /* Set sandbox test data */
  108. priv->data[0] = SANDBOX_ADC_CHANNEL0_DATA;
  109. priv->data[1] = SANDBOX_ADC_CHANNEL1_DATA;
  110. priv->data[2] = SANDBOX_ADC_CHANNEL2_DATA;
  111. priv->data[3] = SANDBOX_ADC_CHANNEL3_DATA;
  112. return 0;
  113. }
  114. int sandbox_adc_ofdata_to_platdata(struct udevice *dev)
  115. {
  116. struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
  117. uc_pdata->data_mask = SANDBOX_ADC_DATA_MASK;
  118. uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
  119. uc_pdata->data_timeout_us = 0;
  120. /* Mask available channel bits: [0:3] */
  121. uc_pdata->channel_mask = (1 << SANDBOX_ADC_CHANNELS) - 1;
  122. return 0;
  123. }
  124. static const struct adc_ops sandbox_adc_ops = {
  125. .start_channel = sandbox_adc_start_channel,
  126. .start_channels = sandbox_adc_start_channels,
  127. .channel_data = sandbox_adc_channel_data,
  128. .channels_data = sandbox_adc_channels_data,
  129. .stop = sandbox_adc_stop,
  130. };
  131. static const struct udevice_id sandbox_adc_ids[] = {
  132. { .compatible = "sandbox,adc" },
  133. { }
  134. };
  135. U_BOOT_DRIVER(sandbox_adc) = {
  136. .name = "sandbox-adc",
  137. .id = UCLASS_ADC,
  138. .of_match = sandbox_adc_ids,
  139. .ops = &sandbox_adc_ops,
  140. .probe = sandbox_adc_probe,
  141. .ofdata_to_platdata = sandbox_adc_ofdata_to_platdata,
  142. .priv_auto_alloc_size = sizeof(struct sandbox_adc_priv),
  143. };