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 /** 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 27 int sandbox_adc_start_channel(struct udevice *dev, int channel) 28 { 29 struct sandbox_adc_priv *priv = dev_get_priv(dev); 30 31 /* Set single-channel mode */ 32 priv->conversion_mode = SANDBOX_ADC_MODE_SINGLE_CHANNEL; 33 /* Select channel */ 34 priv->active_channel_mask = 1 << channel; 35 /* Start conversion */ 36 priv->conversion_status = SANDBOX_ADC_ACTIVE; 37 38 return 0; 39 } 40 41 int sandbox_adc_start_channels(struct udevice *dev, unsigned int channel_mask) 42 { 43 struct sandbox_adc_priv *priv = dev_get_priv(dev); 44 45 /* Set single-channel mode */ 46 priv->conversion_mode = SANDBOX_ADC_MODE_MULTI_CHANNEL; 47 /* Select channel */ 48 priv->active_channel_mask = channel_mask; 49 /* Start conversion */ 50 priv->conversion_status = SANDBOX_ADC_ACTIVE; 51 52 return 0; 53 } 54 55 int sandbox_adc_channel_data(struct udevice *dev, int channel, 56 unsigned int *data) 57 { 58 struct sandbox_adc_priv *priv = dev_get_priv(dev); 59 60 /* For single-channel conversion mode, check if channel was selected */ 61 if ((priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) && 62 !(priv->active_channel_mask & (1 << channel))) { 63 pr_err("Request for an inactive channel!"); 64 return -EINVAL; 65 } 66 67 /* The conversion must be started before reading the data */ 68 if (priv->conversion_status == SANDBOX_ADC_INACTIVE) 69 return -EIO; 70 71 *data = priv->data[channel]; 72 73 return 0; 74 } 75 76 int sandbox_adc_channels_data(struct udevice *dev, unsigned int channel_mask, 77 struct adc_channel *channels) 78 { 79 struct sandbox_adc_priv *priv = dev_get_priv(dev); 80 int i; 81 82 /* Return error for single-channel conversion mode */ 83 if (priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) { 84 pr_err("ADC in single-channel mode!"); 85 return -EPERM; 86 } 87 /* Check channel selection */ 88 if (!(priv->active_channel_mask & channel_mask)) { 89 pr_err("Request for an inactive channel!"); 90 return -EINVAL; 91 } 92 /* The conversion must be started before reading the data */ 93 if (priv->conversion_status == SANDBOX_ADC_INACTIVE) 94 return -EIO; 95 96 for (i = 0; i < SANDBOX_ADC_CHANNELS; i++) { 97 if (!((channel_mask >> i) & 0x1)) 98 continue; 99 100 channels->data = priv->data[i]; 101 channels->id = i; 102 channels++; 103 } 104 105 return 0; 106 } 107 108 int sandbox_adc_stop(struct udevice *dev) 109 { 110 struct sandbox_adc_priv *priv = dev_get_priv(dev); 111 112 /* Start conversion */ 113 priv->conversion_status = SANDBOX_ADC_INACTIVE; 114 115 return 0; 116 } 117 118 int sandbox_adc_probe(struct udevice *dev) 119 { 120 struct sandbox_adc_priv *priv = dev_get_priv(dev); 121 122 /* Stop conversion */ 123 priv->conversion_status = SANDBOX_ADC_INACTIVE; 124 /* Set single-channel mode */ 125 priv->conversion_mode = SANDBOX_ADC_MODE_SINGLE_CHANNEL; 126 /* Deselect all channels */ 127 priv->active_channel_mask = 0; 128 129 /* Set sandbox test data */ 130 priv->data[0] = SANDBOX_ADC_CHANNEL0_DATA; 131 priv->data[1] = SANDBOX_ADC_CHANNEL1_DATA; 132 priv->data[2] = SANDBOX_ADC_CHANNEL2_DATA; 133 priv->data[3] = SANDBOX_ADC_CHANNEL3_DATA; 134 135 return 0; 136 } 137 138 int sandbox_adc_ofdata_to_platdata(struct udevice *dev) 139 { 140 struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); 141 142 uc_pdata->data_mask = SANDBOX_ADC_DATA_MASK; 143 uc_pdata->data_format = ADC_DATA_FORMAT_BIN; 144 uc_pdata->data_timeout_us = 0; 145 146 /* Mask available channel bits: [0:3] */ 147 uc_pdata->channel_mask = (1 << SANDBOX_ADC_CHANNELS) - 1; 148 149 return 0; 150 } 151 152 static const struct adc_ops sandbox_adc_ops = { 153 .start_channel = sandbox_adc_start_channel, 154 .start_channels = sandbox_adc_start_channels, 155 .channel_data = sandbox_adc_channel_data, 156 .channels_data = sandbox_adc_channels_data, 157 .stop = sandbox_adc_stop, 158 }; 159 160 static const struct udevice_id sandbox_adc_ids[] = { 161 { .compatible = "sandbox,adc" }, 162 { } 163 }; 164 165 U_BOOT_DRIVER(sandbox_adc) = { 166 .name = "sandbox-adc", 167 .id = UCLASS_ADC, 168 .of_match = sandbox_adc_ids, 169 .ops = &sandbox_adc_ops, 170 .probe = sandbox_adc_probe, 171 .ofdata_to_platdata = sandbox_adc_ofdata_to_platdata, 172 .priv_auto_alloc_size = sizeof(struct sandbox_adc_priv), 173 }; 174