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