1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * adcxx.c 4 * 5 * The adcxx4s is an AD converter family from National Semiconductor (NS). 6 * 7 * Copyright (c) 2008 Marc Pignat <marc.pignat@hevs.ch> 8 * 9 * The adcxx4s communicates with a host processor via an SPI/Microwire Bus 10 * interface. This driver supports the whole family of devices with name 11 * ADC<bb><c>S<sss>, where 12 * * bb is the resolution in number of bits (8, 10, 12) 13 * * c is the number of channels (1, 2, 4, 8) 14 * * sss is the maximum conversion speed (021 for 200 kSPS, 051 for 500 kSPS 15 * and 101 for 1 MSPS) 16 * 17 * Complete datasheets are available at National's website here: 18 * http://www.national.com/ds/DC/ADC<bb><c>S<sss>.pdf 19 * 20 * Handling of 8, 10 and 12 bits converters are the same, the 21 * unavailable bits are 0 :) 22 */ 23 24 #include <linux/init.h> 25 #include <linux/module.h> 26 #include <linux/kernel.h> 27 #include <linux/slab.h> 28 #include <linux/device.h> 29 #include <linux/err.h> 30 #include <linux/sysfs.h> 31 #include <linux/hwmon.h> 32 #include <linux/hwmon-sysfs.h> 33 #include <linux/mutex.h> 34 #include <linux/spi/spi.h> 35 36 #define DRVNAME "adcxx" 37 38 struct adcxx { 39 struct device *hwmon_dev; 40 struct mutex lock; 41 u32 channels; 42 u32 reference; /* in millivolts */ 43 }; 44 45 /* sysfs hook function */ 46 static ssize_t adcxx_show(struct device *dev, 47 struct device_attribute *devattr, char *buf) 48 { 49 struct spi_device *spi = to_spi_device(dev); 50 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 51 struct adcxx *adc = spi_get_drvdata(spi); 52 u8 tx_buf[2]; 53 u8 rx_buf[2]; 54 int status; 55 u32 value; 56 57 if (mutex_lock_interruptible(&adc->lock)) 58 return -ERESTARTSYS; 59 60 if (adc->channels == 1) { 61 status = spi_read(spi, rx_buf, sizeof(rx_buf)); 62 } else { 63 tx_buf[0] = attr->index << 3; /* other bits are don't care */ 64 status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf), 65 rx_buf, sizeof(rx_buf)); 66 } 67 if (status < 0) { 68 dev_warn(dev, "SPI synch. transfer failed with status %d\n", 69 status); 70 goto out; 71 } 72 73 value = (rx_buf[0] << 8) + rx_buf[1]; 74 dev_dbg(dev, "raw value = 0x%x\n", value); 75 76 value = value * adc->reference >> 12; 77 status = sprintf(buf, "%d\n", value); 78 out: 79 mutex_unlock(&adc->lock); 80 return status; 81 } 82 83 static ssize_t adcxx_min_show(struct device *dev, 84 struct device_attribute *devattr, char *buf) 85 { 86 /* The minimum reference is 0 for this chip family */ 87 return sprintf(buf, "0\n"); 88 } 89 90 static ssize_t adcxx_max_show(struct device *dev, 91 struct device_attribute *devattr, char *buf) 92 { 93 struct spi_device *spi = to_spi_device(dev); 94 struct adcxx *adc = spi_get_drvdata(spi); 95 u32 reference; 96 97 if (mutex_lock_interruptible(&adc->lock)) 98 return -ERESTARTSYS; 99 100 reference = adc->reference; 101 102 mutex_unlock(&adc->lock); 103 104 return sprintf(buf, "%d\n", reference); 105 } 106 107 static ssize_t adcxx_max_store(struct device *dev, 108 struct device_attribute *devattr, 109 const char *buf, size_t count) 110 { 111 struct spi_device *spi = to_spi_device(dev); 112 struct adcxx *adc = spi_get_drvdata(spi); 113 unsigned long value; 114 115 if (kstrtoul(buf, 10, &value)) 116 return -EINVAL; 117 118 if (mutex_lock_interruptible(&adc->lock)) 119 return -ERESTARTSYS; 120 121 adc->reference = value; 122 123 mutex_unlock(&adc->lock); 124 125 return count; 126 } 127 128 static ssize_t adcxx_name_show(struct device *dev, 129 struct device_attribute *devattr, char *buf) 130 { 131 return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); 132 } 133 134 static struct sensor_device_attribute ad_input[] = { 135 SENSOR_ATTR_RO(name, adcxx_name, 0), 136 SENSOR_ATTR_RO(in_min, adcxx_min, 0), 137 SENSOR_ATTR_RW(in_max, adcxx_max, 0), 138 SENSOR_ATTR_RO(in0_input, adcxx, 0), 139 SENSOR_ATTR_RO(in1_input, adcxx, 1), 140 SENSOR_ATTR_RO(in2_input, adcxx, 2), 141 SENSOR_ATTR_RO(in3_input, adcxx, 3), 142 SENSOR_ATTR_RO(in4_input, adcxx, 4), 143 SENSOR_ATTR_RO(in5_input, adcxx, 5), 144 SENSOR_ATTR_RO(in6_input, adcxx, 6), 145 SENSOR_ATTR_RO(in7_input, adcxx, 7), 146 }; 147 148 /*----------------------------------------------------------------------*/ 149 150 static int adcxx_probe(struct spi_device *spi) 151 { 152 int channels = spi_get_device_id(spi)->driver_data; 153 struct adcxx *adc; 154 int status; 155 int i; 156 157 adc = devm_kzalloc(&spi->dev, sizeof(*adc), GFP_KERNEL); 158 if (!adc) 159 return -ENOMEM; 160 161 /* set a default value for the reference */ 162 adc->reference = 3300; 163 adc->channels = channels; 164 mutex_init(&adc->lock); 165 166 mutex_lock(&adc->lock); 167 168 spi_set_drvdata(spi, adc); 169 170 for (i = 0; i < 3 + adc->channels; i++) { 171 status = device_create_file(&spi->dev, &ad_input[i].dev_attr); 172 if (status) { 173 dev_err(&spi->dev, "device_create_file failed.\n"); 174 goto out_err; 175 } 176 } 177 178 adc->hwmon_dev = hwmon_device_register(&spi->dev); 179 if (IS_ERR(adc->hwmon_dev)) { 180 dev_err(&spi->dev, "hwmon_device_register failed.\n"); 181 status = PTR_ERR(adc->hwmon_dev); 182 goto out_err; 183 } 184 185 mutex_unlock(&adc->lock); 186 return 0; 187 188 out_err: 189 for (i--; i >= 0; i--) 190 device_remove_file(&spi->dev, &ad_input[i].dev_attr); 191 192 mutex_unlock(&adc->lock); 193 return status; 194 } 195 196 static void adcxx_remove(struct spi_device *spi) 197 { 198 struct adcxx *adc = spi_get_drvdata(spi); 199 int i; 200 201 mutex_lock(&adc->lock); 202 hwmon_device_unregister(adc->hwmon_dev); 203 for (i = 0; i < 3 + adc->channels; i++) 204 device_remove_file(&spi->dev, &ad_input[i].dev_attr); 205 206 mutex_unlock(&adc->lock); 207 } 208 209 static const struct spi_device_id adcxx_ids[] = { 210 { "adcxx1s", 1 }, 211 { "adcxx2s", 2 }, 212 { "adcxx4s", 4 }, 213 { "adcxx8s", 8 }, 214 { }, 215 }; 216 MODULE_DEVICE_TABLE(spi, adcxx_ids); 217 218 static struct spi_driver adcxx_driver = { 219 .driver = { 220 .name = "adcxx", 221 }, 222 .id_table = adcxx_ids, 223 .probe = adcxx_probe, 224 .remove = adcxx_remove, 225 }; 226 227 module_spi_driver(adcxx_driver); 228 229 MODULE_AUTHOR("Marc Pignat"); 230 MODULE_DESCRIPTION("National Semiconductor adcxx8sxxx Linux driver"); 231 MODULE_LICENSE("GPL"); 232