sandbox.c 4.4 KB

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