blob: fd4524e718060447e84d46bd488622554bc34be7 [file] [log] [blame]
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -07001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -070013#include <linux/kernel.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070014#include <linux/module.h>
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -070015#include <linux/init.h>
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -070016#include <linux/fs.h>
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -070017#include <linux/mutex.h>
18#include <linux/err.h>
19#include <linux/slab.h>
20#include <linux/gpio.h>
21#include <linux/hwmon.h>
22#include <linux/delay.h>
23#include <linux/epm_adc.h>
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -070024#include <linux/uaccess.h>
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -070025#include <linux/spi/spi.h>
26#include <linux/hwmon-sysfs.h>
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -070027#include <linux/miscdevice.h>
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -070028#include <linux/platform_device.h>
29
30#define EPM_ADC_DRIVER_NAME "epm_adc"
31#define EPM_ADC_MAX_FNAME 20
32#define EPM_ADC_CONVERSION_DELAY 100 /* milliseconds */
33/* Command Bits */
34#define EPM_ADC_ADS_SPI_BITS_PER_WORD 8
35#define EPM_ADC_ADS_DATA_READ_CMD (0x1 << 5)
36#define EPM_ADC_ADS_REG_READ_CMD (0x2 << 5)
37#define EPM_ADC_ADS_REG_WRITE_CMD (0x3 << 5)
38#define EPM_ADC_ADS_PULSE_CONVERT_CMD (0x4 << 5)
39#define EPM_ADC_ADS_MULTIPLE_REG_ACCESS (0x1 << 4)
40/* Register map */
41#define EPM_ADC_ADS_CONFIG0_REG_ADDR 0x0
42#define EPM_ADC_ADS_CONFIG1_REG_ADDR 0x1
43#define EPM_ADC_ADS_MUXSG0_REG_ADDR 0x4
44#define EPM_ADC_ADS_MUXSG1_REG_ADDR 0x5
45/* Register map default data */
46#define EPM_ADC_ADS_REG0_DEFAULT 0x2
47#define EPM_ADC_ADS_REG1_DEFAULT 0x52
48#define EPM_ADC_ADS_CHANNEL_DATA_CHID 0x1f
49/* Channel ID */
50#define EPM_ADC_ADS_CHANNEL_OFFSET 0x18
51#define EPM_ADC_ADS_CHANNEL_VCC 0x1a
52#define EPM_ADC_ADS_CHANNEL_TEMP 0x1b
53#define EPM_ADC_ADS_CHANNEL_GAIN 0x1c
54#define EPM_ADC_ADS_CHANNEL_REF 0x1d
55/* Scaling data co-efficients */
56#define EPM_ADC_SCALE_MILLI 1000
57#define EPM_ADC_SCALE_CODE_VOLTS 3072
58#define EPM_ADC_SCALE_CODE_GAIN 30720
59#define EPM_ADC_TEMP_SENSOR_COEFF 394
60#define EPM_ADC_TEMP_TO_DEGC_COEFF 168000
61#define EPM_ADC_CHANNEL_AIN_OFFSET 8
62#define EPM_ADC_MAX_NEGATIVE_SCALE_CODE 0x8000
63#define EPM_ADC_NEG_LSB_CODE 0xffff
64#define EPM_ADC_VREF_CODE 0x7800
65#define EPM_ADC_MILLI_VOLTS_SOURCE 4750
66#define EPM_ADC_SCALE_FACTOR 64
67#define GPIO_EPM_GLOBAL_ENABLE 86
68#define EPM_ADC_CONVERSION_TIME_MIN 50000
69#define EPM_ADC_CONVERSION_TIME_MAX 51000
70
71struct epm_adc_drv {
72 struct platform_device *pdev;
73 struct device *hwmon;
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -070074 struct spi_device *epm_spi_client;
75 struct mutex conv_lock;
76 uint32_t bus_id;
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -070077 struct miscdevice misc;
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -070078};
79
80static struct epm_adc_drv *epm_adc_drv;
81static struct i2c_board_info *epm_i2c_info;
82static bool epm_adc_first_request;
83static int epm_gpio_expander_base_addr;
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -070084static bool epm_adc_expander_register;
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -070085
86#define GPIO_EPM_EXPANDER_IO0 epm_gpio_expander_base_addr
87#define GPIO_PWR_MON_ENABLE (GPIO_EPM_EXPANDER_IO0 + 1)
88#define GPIO_ADC1_PWDN_N (GPIO_PWR_MON_ENABLE + 1)
89#define GPIO_PWR_MON_RESET_N (GPIO_ADC1_PWDN_N + 1)
90#define GPIO_EPM_SPI_ADC1_CS_N (GPIO_PWR_MON_RESET_N + 1)
91#define GPIO_PWR_MON_START (GPIO_EPM_SPI_ADC1_CS_N + 1)
92#define GPIO_ADC1_DRDY_N (GPIO_PWR_MON_START + 1)
93#define GPIO_ADC2_PWDN_N (GPIO_ADC1_DRDY_N + 1)
94#define GPIO_EPM_SPI_ADC2_CS_N (GPIO_ADC2_PWDN_N + 1)
95#define GPIO_ADC2_DRDY_N (GPIO_EPM_SPI_ADC2_CS_N + 1)
96
97static int epm_adc_i2c_expander_register(void)
98{
99 int rc = 0;
100 static struct i2c_adapter *i2c_adap;
101 static struct i2c_client *epm_i2c_client;
102
103 rc = gpio_request(GPIO_EPM_GLOBAL_ENABLE, "EPM_GLOBAL_EN");
104 if (!rc) {
105 gpio_direction_output(GPIO_EPM_GLOBAL_ENABLE, 1);
106 } else {
107 pr_err("%s: Configure EPM_GLOBAL_EN Failed\n", __func__);
108 return rc;
109 }
110
111 usleep_range(EPM_ADC_CONVERSION_TIME_MIN,
112 EPM_ADC_CONVERSION_TIME_MAX);
113
114 i2c_adap = i2c_get_adapter(epm_adc_drv->bus_id);
115 if (i2c_adap == NULL) {
116 pr_err("%s: i2c_get_adapter() failed\n", __func__);
117 return -EINVAL;
118 }
119
120 usleep_range(EPM_ADC_CONVERSION_TIME_MIN,
121 EPM_ADC_CONVERSION_TIME_MAX);
122
123 epm_i2c_client = i2c_new_device(i2c_adap, epm_i2c_info);
124 if (IS_ERR(epm_i2c_client)) {
125 pr_err("Error with i2c epm device register\n");
126 return -ENODEV;
127 }
128
129 epm_adc_first_request = false;
130
131 return 0;
132}
133
134static int epm_adc_gpio_configure_expander_enable(void)
135{
136 int rc = 0;
137
138 if (epm_adc_first_request) {
139 rc = gpio_request(GPIO_EPM_GLOBAL_ENABLE, "EPM_GLOBAL_EN");
140 if (!rc) {
141 gpio_direction_output(GPIO_EPM_GLOBAL_ENABLE, 1);
142 } else {
143 pr_err("%s: Configure EPM_GLOBAL_EN Failed\n",
144 __func__);
145 return rc;
146 }
147 } else {
148 epm_adc_first_request = true;
149 }
150
151 usleep_range(EPM_ADC_CONVERSION_TIME_MIN,
152 EPM_ADC_CONVERSION_TIME_MAX);
153
154 rc = gpio_request(GPIO_PWR_MON_ENABLE, "GPIO_PWR_MON_ENABLE");
155 if (!rc) {
156 rc = gpio_direction_output(GPIO_PWR_MON_ENABLE, 1);
157 if (rc) {
158 pr_err("%s: Set GPIO_PWR_MON_ENABLE failed\n",
159 __func__);
160 return rc;
161 }
162 } else {
163 pr_err("%s: gpio_request GPIO_PWR_MON_ENABLE failed\n",
164 __func__);
165 return rc;
166 }
167
168 rc = gpio_request(GPIO_ADC1_PWDN_N, "GPIO_ADC1_PWDN_N");
169 if (!rc) {
170 rc = gpio_direction_output(GPIO_ADC1_PWDN_N, 1);
171 if (rc) {
172 pr_err("%s: Set GPIO_ADC1_PWDN_N failed\n", __func__);
173 return rc;
174 }
175 } else {
176 pr_err("%s: gpio_request GPIO_ADC1_PWDN_N failed\n", __func__);
177 return rc;
178 }
179
180 rc = gpio_request(GPIO_ADC2_PWDN_N, "GPIO_ADC2_PWDN_N");
181 if (!rc) {
182 rc = gpio_direction_output(GPIO_ADC2_PWDN_N, 1);
183 if (rc) {
184 pr_err("%s: Set GPIO_ADC2_PWDN_N failed\n",
185 __func__);
186 return rc;
187 }
188 } else {
189 pr_err("%s: gpio_request GPIO_ADC2_PWDN_N failed\n",
190 __func__);
191 return rc;
192 }
193
194 rc = gpio_request(GPIO_EPM_SPI_ADC1_CS_N, "GPIO_EPM_SPI_ADC1_CS_N");
195 if (!rc) {
196 rc = gpio_direction_output(GPIO_EPM_SPI_ADC1_CS_N, 1);
197 if (rc) {
198 pr_err("%s:Set GPIO_EPM_SPI_ADC1_CS_N failed\n",
199 __func__);
200 return rc;
201 }
202 } else {
203 pr_err("%s: gpio_request GPIO_EPM_SPI_ADC1_CS_N failed\n",
204 __func__);
205 return rc;
206 }
207
208 rc = gpio_request(GPIO_EPM_SPI_ADC2_CS_N,
209 "GPIO_EPM_SPI_ADC2_CS_N");
210 if (!rc) {
211 rc = gpio_direction_output(GPIO_EPM_SPI_ADC2_CS_N, 1);
212 if (rc) {
213 pr_err("%s: Set GPIO_EPM_SPI_ADC2_CS_N "
214 "failed\n", __func__);
215 return rc;
216 }
217 } else {
218 pr_err("%s: gpio_request GPIO_EPM_SPI_ADC2_CS_N "
219 "failed\n", __func__);
220 return rc;
221 }
222
223 rc = gpio_direction_output(GPIO_EPM_SPI_ADC1_CS_N, 0);
224 if (rc) {
225 pr_err("%s:Reset GPIO_EPM_SPI_ADC1_CS_N failed\n", __func__);
226 return rc;
227 }
228
229 rc = gpio_direction_output(GPIO_EPM_SPI_ADC1_CS_N, 1);
230 if (rc) {
231 pr_err("%s: Set GPIO_EPM_SPI_ADC1_CS_N failed\n", __func__);
232 return rc;
233 }
234
235 rc = gpio_request(GPIO_PWR_MON_START, "GPIO_PWR_MON_START");
236 if (!rc) {
237 rc = gpio_direction_output(GPIO_PWR_MON_START, 0);
238 if (rc) {
239 pr_err("%s: Reset GPIO_PWR_MON_START failed\n",
240 __func__);
241 return rc;
242 }
243 } else {
244 pr_err("%s: gpio_request GPIO_PWR_MON_START failed\n",
245 __func__);
246 return rc;
247 }
248
249 rc = gpio_request(GPIO_PWR_MON_RESET_N, "GPIO_PWR_MON_RESET_N");
250 if (!rc) {
251 rc = gpio_direction_output(GPIO_PWR_MON_RESET_N, 0);
252 if (rc) {
253 pr_err("%s: Reset GPIO_PWR_MON_RESET_N failed\n",
254 __func__);
255 return rc;
256 }
257 } else {
258 pr_err("%s: gpio_request GPIO_PWR_MON_RESET_N failed\n",
259 __func__);
260 return rc;
261 }
262
263 rc = gpio_direction_output(GPIO_PWR_MON_RESET_N, 1);
264 if (rc) {
265 pr_err("%s: Set GPIO_PWR_MON_RESET_N failed\n", __func__);
266 return rc;
267 }
268
269 rc = gpio_direction_output(GPIO_EPM_SPI_ADC1_CS_N, 0);
270 if (rc) {
271 pr_err("%s:Reset GPIO_EPM_SPI_ADC1_CS_N failed\n", __func__);
272 return rc;
273 }
274 return rc;
275}
276
277static int epm_adc_gpio_configure_expander_disable(void)
278{
279 int rc = 0;
280 gpio_free(GPIO_PWR_MON_ENABLE);
281 gpio_free(GPIO_ADC1_PWDN_N);
282 gpio_free(GPIO_ADC2_PWDN_N);
283 gpio_free(GPIO_EPM_SPI_ADC1_CS_N);
284 gpio_free(GPIO_EPM_SPI_ADC2_CS_N);
285 gpio_free(GPIO_PWR_MON_START);
286 gpio_free(GPIO_PWR_MON_RESET_N);
287 rc = gpio_direction_output(GPIO_EPM_GLOBAL_ENABLE, 0);
288 if (rc)
289 pr_debug("%s: Disable EPM_GLOBAL_EN Failed\n", __func__);
290 gpio_free(GPIO_EPM_GLOBAL_ENABLE);
291 return rc;
292}
293
294static int epm_adc_spi_chip_select(int32_t id)
295{
296 int rc = 0;
297 if (id == 0) {
298 rc = gpio_direction_output(GPIO_EPM_SPI_ADC2_CS_N, 1);
299 if (rc) {
300 pr_err("%s:Disable SPI_ADC2_CS failed",
301 __func__);
302 return rc;
303 }
304
305 rc = gpio_direction_output(GPIO_EPM_SPI_ADC1_CS_N, 0);
306 if (rc) {
307 pr_err("%s:Enable SPI_ADC1_CS failed", __func__);
308 return rc;
309 }
310 } else if (id == 1) {
311 rc = gpio_direction_output(GPIO_EPM_SPI_ADC1_CS_N, 1);
312 if (rc) {
313 pr_err("%s:Disable SPI_ADC1_CS failed", __func__);
314 return rc;
315 }
316 rc = gpio_direction_output(GPIO_EPM_SPI_ADC2_CS_N, 0);
317 if (rc) {
318 pr_err("%s:Enable SPI_ADC2_CS failed", __func__);
319 return rc;
320 }
321 } else {
322 rc = -EFAULT;
323 }
324 return rc;
325}
326
327static int epm_adc_ads_spi_write(struct epm_adc_drv *epm_adc,
328 uint8_t addr, uint8_t val)
329{
330 struct spi_message m;
331 struct spi_transfer t;
332 char tx_buf[2];
333 int rc = 0;
334
335 spi_setup(epm_adc->epm_spi_client);
336
337 memset(&t, 0, sizeof t);
338 memset(tx_buf, 0, sizeof tx_buf);
339 t.tx_buf = tx_buf;
340 spi_message_init(&m);
341 spi_message_add_tail(&t, &m);
342
343 tx_buf[0] = EPM_ADC_ADS_REG_WRITE_CMD | addr;
344 tx_buf[1] = val;
345
346 t.len = sizeof(tx_buf);
347 t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
348
349 rc = spi_sync(epm_adc->epm_spi_client, &m);
350
351 return rc;
352}
353
354static int epm_adc_init_ads(struct epm_adc_drv *epm_adc)
355{
356 int rc = 0;
357
358 rc = epm_adc_ads_spi_write(epm_adc, EPM_ADC_ADS_CONFIG0_REG_ADDR,
359 EPM_ADC_ADS_REG0_DEFAULT);
360 if (rc)
361 return rc;
362
363 rc = epm_adc_ads_spi_write(epm_adc, EPM_ADC_ADS_CONFIG1_REG_ADDR,
364 EPM_ADC_ADS_REG1_DEFAULT);
365 if (rc)
366 return rc;
367 return rc;
368}
369
370static int epm_adc_ads_pulse_convert(struct epm_adc_drv *epm_adc)
371{
372 struct spi_message m;
373 struct spi_transfer t;
374 char tx_buf[1];
375 int rc = 0;
376
377 spi_setup(epm_adc->epm_spi_client);
378
379 memset(&t, 0, sizeof t);
380 memset(tx_buf, 0, sizeof tx_buf);
381 t.tx_buf = tx_buf;
382 spi_message_init(&m);
383 spi_message_add_tail(&t, &m);
384
385 tx_buf[0] = EPM_ADC_ADS_PULSE_CONVERT_CMD;
386 t.len = sizeof(tx_buf);
387 t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
388
389 rc = spi_sync(epm_adc->epm_spi_client, &m);
390
391 return rc;
392}
393
394static int epm_adc_ads_read_data(struct epm_adc_drv *epm_adc, char *adc_data)
395{
396 struct spi_message m;
397 struct spi_transfer t;
398 char tx_buf[4], rx_buf[4];
399 int rc = 0;
400
401 spi_setup(epm_adc->epm_spi_client);
402
403 memset(&t, 0, sizeof t);
404 memset(tx_buf, 0, sizeof tx_buf);
405 memset(rx_buf, 0, sizeof tx_buf);
406 t.tx_buf = tx_buf;
407 t.rx_buf = rx_buf;
408 spi_message_init(&m);
409 spi_message_add_tail(&t, &m);
410
411 tx_buf[0] = EPM_ADC_ADS_DATA_READ_CMD |
412 EPM_ADC_ADS_MULTIPLE_REG_ACCESS;
413
414 t.len = sizeof(tx_buf);
415 t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
416
417 rc = spi_sync(epm_adc->epm_spi_client, &m);
418 if (rc)
419 return rc;
420
421 rc = spi_sync(epm_adc->epm_spi_client, &m);
422 if (rc)
423 return rc;
424
425 rc = spi_sync(epm_adc->epm_spi_client, &m);
426 if (rc)
427 return rc;
428
429 adc_data[0] = rx_buf[1];
430 adc_data[1] = rx_buf[2];
431 adc_data[2] = rx_buf[3];
432
433 return rc;
434}
435
436static int epm_adc_hw_init(struct epm_adc_drv *epm_adc)
437{
438 int rc = 0;
439
440 mutex_lock(&epm_adc->conv_lock);
441 rc = epm_adc_gpio_configure_expander_enable();
442 if (rc != 0) {
443 pr_err("epm gpio configure expander failed, rc = %d\n", rc);
444 goto epm_adc_hw_init_err;
445 }
446 rc = epm_adc_init_ads(epm_adc);
447 if (rc) {
448 pr_err("epm_adc_init_ads failed, rc=%d\n", rc);
449 goto epm_adc_hw_init_err;
450 }
451
452epm_adc_hw_init_err:
453 mutex_unlock(&epm_adc->conv_lock);
454 return rc;
455}
456
457static int epm_adc_hw_deinit(struct epm_adc_drv *epm_adc)
458{
459 int rc = 0;
460
461 mutex_lock(&epm_adc->conv_lock);
462 rc = epm_adc_gpio_configure_expander_disable();
463 if (rc != 0) {
464 pr_err("epm gpio configure expander disable failed,"
465 " rc = %d\n", rc);
466 goto epm_adc_hw_deinit_err;
467 }
468
469epm_adc_hw_deinit_err:
470 mutex_unlock(&epm_adc->conv_lock);
471 return rc;
472}
473
474static int epm_adc_ads_scale_result(struct epm_adc_drv *epm_adc,
475 uint8_t *adc_raw_data, struct epm_chan_request *conv)
476{
477 uint32_t channel_num;
478 int16_t sign_bit;
479 struct epm_adc_platform_data *pdata = epm_adc->pdev->dev.platform_data;
480 uint32_t chan_idx = (conv->device_idx * pdata->chan_per_adc) +
481 conv->channel_idx;
482 int32_t *adc_scaled_data = &conv->physical;
483
484 /* Get the channel number */
485 channel_num = (adc_raw_data[0] & EPM_ADC_ADS_CHANNEL_DATA_CHID);
486 sign_bit = 1;
487 /* This is the 16-bit raw data */
488 *adc_scaled_data = ((adc_raw_data[1] << 8) | adc_raw_data[2]);
489 /* Obtain the internal system reading */
490 if (channel_num == EPM_ADC_ADS_CHANNEL_VCC) {
491 *adc_scaled_data *= EPM_ADC_SCALE_MILLI;
492 *adc_scaled_data /= EPM_ADC_SCALE_CODE_VOLTS;
493 } else if (channel_num == EPM_ADC_ADS_CHANNEL_GAIN) {
494 *adc_scaled_data /= EPM_ADC_SCALE_CODE_GAIN;
495 } else if (channel_num == EPM_ADC_ADS_CHANNEL_REF) {
496 *adc_scaled_data *= EPM_ADC_SCALE_MILLI;
497 *adc_scaled_data /= EPM_ADC_SCALE_CODE_VOLTS;
498 } else if (channel_num == EPM_ADC_ADS_CHANNEL_TEMP) {
499 /* Convert Code to micro-volts */
500 /* Use this formula to get the temperature reading */
501 *adc_scaled_data -= EPM_ADC_TEMP_TO_DEGC_COEFF;
502 *adc_scaled_data /= EPM_ADC_TEMP_SENSOR_COEFF;
503 } else if (channel_num == EPM_ADC_ADS_CHANNEL_OFFSET) {
504 /* The offset should be zero */
505 pr_debug("%s: ADC Channel Offset\n", __func__);
506 return -EFAULT;
507 } else {
508 channel_num -= EPM_ADC_CHANNEL_AIN_OFFSET;
509 /*
510 * Conversion for the adc channels.
511 * mvVRef is in milli-volts and resistorValue is in micro-ohms.
512 * Hence, I = V/R gives us current in kilo-amps.
513 */
514 if (*adc_scaled_data & EPM_ADC_MAX_NEGATIVE_SCALE_CODE) {
515 sign_bit = -1;
516 *adc_scaled_data = (~*adc_scaled_data
517 & EPM_ADC_NEG_LSB_CODE);
518 }
519 if (*adc_scaled_data != 0) {
520 *adc_scaled_data *= EPM_ADC_SCALE_FACTOR;
521 /* Device is calibrated for 1LSB = VREF/7800h.*/
522 *adc_scaled_data *= EPM_ADC_MILLI_VOLTS_SOURCE;
523 *adc_scaled_data /= EPM_ADC_VREF_CODE;
524 /* Data will now be in micro-volts.*/
525 *adc_scaled_data *= EPM_ADC_SCALE_MILLI;
526 /* Divide by amplifier gain value.*/
527 *adc_scaled_data /= pdata->channel[chan_idx].gain;
528 /* Data will now be in nano-volts.*/
529 *adc_scaled_data /= EPM_ADC_SCALE_FACTOR;
530 *adc_scaled_data *= EPM_ADC_SCALE_MILLI;
531 /* Data is now in micro-amps.*/
532 *adc_scaled_data /=
533 pdata->channel[chan_idx].resistorValue;
534 /* Set the sign bit for lekage current. */
535 *adc_scaled_data *= sign_bit;
536 }
537 }
538 return 0;
539}
540
541static int epm_adc_blocking_conversion(struct epm_adc_drv *epm_adc,
542 struct epm_chan_request *conv)
543{
544 struct epm_adc_platform_data *pdata = epm_adc->pdev->dev.platform_data;
545 int32_t channel_num = 0, mux_chan_idx = 0;
546 char adc_data[3];
547 int rc = 0;
548
549 mutex_lock(&epm_adc->conv_lock);
550
551 rc = epm_adc_spi_chip_select(conv->device_idx);
552 if (rc) {
553 pr_err("epm_adc_chip_select failed, rc=%d\n", rc);
554 goto conv_err;
555 }
556
557 if (conv->channel_idx < pdata->chan_per_mux) {
558 /* Reset MUXSG1_REGISTER */
559 rc = epm_adc_ads_spi_write(epm_adc, EPM_ADC_ADS_MUXSG1_REG_ADDR,
560 0x0);
561 if (rc)
562 goto conv_err;
563
564 mux_chan_idx = 1 << conv->channel_idx;
565 /* Select Channel index in MUXSG0_REGISTER */
566 rc = epm_adc_ads_spi_write(epm_adc, EPM_ADC_ADS_MUXSG0_REG_ADDR,
567 mux_chan_idx);
568 if (rc)
569 goto conv_err;
570 } else {
571 /* Reset MUXSG0_REGISTER */
572 rc = epm_adc_ads_spi_write(epm_adc, EPM_ADC_ADS_MUXSG0_REG_ADDR,
573 0x0);
574 if (rc)
575 goto conv_err;
576
577 mux_chan_idx = 1 << (conv->channel_idx - pdata->chan_per_mux);
578 /* Select Channel index in MUXSG1_REGISTER */
579 rc = epm_adc_ads_spi_write(epm_adc, EPM_ADC_ADS_MUXSG1_REG_ADDR,
580 mux_chan_idx);
581 if (rc)
582 goto conv_err;
583 }
584
585 rc = epm_adc_ads_pulse_convert(epm_adc);
586 if (rc) {
587 pr_err("epm_adc_ads_pulse_convert failed, rc=%d\n", rc);
588 goto conv_err;
589 }
590
591 rc = epm_adc_ads_read_data(epm_adc, adc_data);
592 if (rc) {
593 pr_err("epm_adc_ads_read_data failed, rc=%d\n", rc);
594 goto conv_err;
595 }
596
597 channel_num = (adc_data[0] & EPM_ADC_ADS_CHANNEL_DATA_CHID);
598 pr_debug("ADC data Read: adc_data =%d, %d, %d\n",
599 adc_data[0], adc_data[1], adc_data[2]);
600
601 epm_adc_ads_scale_result(epm_adc, (uint8_t *)adc_data, conv);
602
603 pr_debug("channel_num(0x) = %x, scaled_data = %d\n",
604 (channel_num - EPM_ADC_ADS_SPI_BITS_PER_WORD),
605 conv->physical);
606conv_err:
607 mutex_unlock(&epm_adc->conv_lock);
608 return rc;
609}
610
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -0700611static long epm_adc_ioctl(struct file *file, unsigned int cmd,
612 unsigned long arg)
613{
614 struct epm_adc_drv *epm_adc = epm_adc_drv;
615
616 switch (cmd) {
617 case EPM_ADC_REQUEST:
618 {
619 struct epm_chan_request conv;
620 int rc;
621
622 if (copy_from_user(&conv, (void __user *)arg,
623 sizeof(struct epm_chan_request)))
624 return -EFAULT;
625
626 rc = epm_adc_blocking_conversion(epm_adc, &conv);
627 if (rc) {
628 pr_err("Failed EPM conversion:%d\n", rc);
629 return rc;
630 }
631
632 if (copy_to_user((void __user *)arg, &conv,
633 sizeof(struct epm_chan_request)))
634 return -EFAULT;
635 break;
636 }
637 case EPM_ADC_INIT:
638 {
639 uint32_t result;
640 if (!epm_adc_expander_register) {
641 result = epm_adc_i2c_expander_register();
642 if (result) {
643 pr_err("Failed i2c register:%d\n",
644 result);
645 return result;
646 }
647 epm_adc_expander_register = true;
648 }
649
650 result = epm_adc_hw_init(epm_adc_drv);
651
652 if (copy_to_user((void __user *)arg, &result,
653 sizeof(uint32_t)))
654 return -EFAULT;
655 break;
656 }
657 case EPM_ADC_DEINIT:
658 {
659 uint32_t result;
660 result = epm_adc_hw_deinit(epm_adc_drv);
661
662 if (copy_to_user((void __user *)arg, &result,
663 sizeof(uint32_t)))
664 return -EFAULT;
665 break;
666 }
667 default:
668 return -EINVAL;
669 }
670
671 return 0;
672}
673
674const struct file_operations epm_adc_fops = {
675 .unlocked_ioctl = epm_adc_ioctl,
676};
677
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700678static ssize_t epm_adc_show_in(struct device *dev,
679 struct device_attribute *devattr, char *buf)
680{
681 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
682 struct epm_adc_drv *epm_adc = dev_get_drvdata(dev);
683 struct epm_adc_platform_data *pdata = epm_adc->pdev->dev.platform_data;
684 struct epm_chan_request conv;
685 int rc = 0;
686
687 conv.device_idx = attr->index / pdata->chan_per_adc;
688 conv.channel_idx = attr->index % pdata->chan_per_adc;
689 conv.physical = 0;
690 pr_debug("%s: device_idx=%d channel_idx=%d", __func__, conv.device_idx,
691 conv.channel_idx);
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -0700692 if (!epm_adc_expander_register) {
693 rc = epm_adc_i2c_expander_register();
694 if (rc) {
695 pr_err("I2C expander register failed:%d\n", rc);
696 return rc;
697 }
698 epm_adc_expander_register = true;
699 }
700
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700701 rc = epm_adc_hw_init(epm_adc);
702 if (rc) {
703 pr_err("%s: epm_adc_hw_init() failed, rc = %d",
704 __func__, rc);
705 return 0;
706 }
707
708 rc = epm_adc_blocking_conversion(epm_adc, &conv);
709 if (rc) {
710 pr_err("%s: epm_adc_blocking_conversion() failed, rc = %d\n",
711 __func__, rc);
712 return 0;
713 }
714 rc = epm_adc_hw_deinit(epm_adc);
715 if (rc) {
716 pr_err("%s: epm_adc_hw_deinit() failed, rc = %d",
717 __func__, rc);
718 return 0;
719 }
720
721 return snprintf(buf, 16, "Result: %d\n", conv.physical);
722}
723
Stephen Boydaeaf2ad2012-07-03 14:33:25 -0700724static struct sensor_device_attribute epm_adc_in_attrs[] = {
725 SENSOR_ATTR(ads0_chan0, S_IRUGO, epm_adc_show_in, NULL, 0),
726 SENSOR_ATTR(ads0_chan1, S_IRUGO, epm_adc_show_in, NULL, 1),
727 SENSOR_ATTR(ads0_chan2, S_IRUGO, epm_adc_show_in, NULL, 2),
728 SENSOR_ATTR(ads0_chan3, S_IRUGO, epm_adc_show_in, NULL, 3),
729 SENSOR_ATTR(ads0_chan4, S_IRUGO, epm_adc_show_in, NULL, 4),
730 SENSOR_ATTR(ads0_chan5, S_IRUGO, epm_adc_show_in, NULL, 5),
731 SENSOR_ATTR(ads0_chan6, S_IRUGO, epm_adc_show_in, NULL, 6),
732 SENSOR_ATTR(ads0_chan7, S_IRUGO, epm_adc_show_in, NULL, 7),
733 SENSOR_ATTR(ads0_chan8, S_IRUGO, epm_adc_show_in, NULL, 8),
734 SENSOR_ATTR(ads0_chan9, S_IRUGO, epm_adc_show_in, NULL, 9),
735 SENSOR_ATTR(ads0_chan10, S_IRUGO, epm_adc_show_in, NULL, 10),
736 SENSOR_ATTR(ads0_chan11, S_IRUGO, epm_adc_show_in, NULL, 11),
737 SENSOR_ATTR(ads0_chan12, S_IRUGO, epm_adc_show_in, NULL, 12),
738 SENSOR_ATTR(ads0_chan13, S_IRUGO, epm_adc_show_in, NULL, 13),
739 SENSOR_ATTR(ads0_chan14, S_IRUGO, epm_adc_show_in, NULL, 14),
740 SENSOR_ATTR(ads0_chan15, S_IRUGO, epm_adc_show_in, NULL, 15),
741 SENSOR_ATTR(ads1_chan0, S_IRUGO, epm_adc_show_in, NULL, 16),
742 SENSOR_ATTR(ads1_chan1, S_IRUGO, epm_adc_show_in, NULL, 17),
743 SENSOR_ATTR(ads1_chan2, S_IRUGO, epm_adc_show_in, NULL, 18),
744 SENSOR_ATTR(ads1_chan3, S_IRUGO, epm_adc_show_in, NULL, 19),
745 SENSOR_ATTR(ads1_chan4, S_IRUGO, epm_adc_show_in, NULL, 20),
746 SENSOR_ATTR(ads1_chan5, S_IRUGO, epm_adc_show_in, NULL, 21),
747 SENSOR_ATTR(ads1_chan6, S_IRUGO, epm_adc_show_in, NULL, 22),
748 SENSOR_ATTR(ads1_chan7, S_IRUGO, epm_adc_show_in, NULL, 23),
749 SENSOR_ATTR(ads1_chan8, S_IRUGO, epm_adc_show_in, NULL, 24),
750 SENSOR_ATTR(ads1_chan9, S_IRUGO, epm_adc_show_in, NULL, 25),
751 SENSOR_ATTR(ads1_chan10, S_IRUGO, epm_adc_show_in, NULL, 26),
752 SENSOR_ATTR(ads1_chan11, S_IRUGO, epm_adc_show_in, NULL, 27),
753 SENSOR_ATTR(ads1_chan12, S_IRUGO, epm_adc_show_in, NULL, 28),
754 SENSOR_ATTR(ads1_chan13, S_IRUGO, epm_adc_show_in, NULL, 29),
755 SENSOR_ATTR(ads1_chan14, S_IRUGO, epm_adc_show_in, NULL, 30),
756 SENSOR_ATTR(ads1_chan15, S_IRUGO, epm_adc_show_in, NULL, 31),
757};
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700758
759static int __devinit epm_adc_init_hwmon(struct platform_device *pdev,
760 struct epm_adc_drv *epm_adc)
761{
762 struct epm_adc_platform_data *pdata = pdev->dev.platform_data;
Stephen Boydaeaf2ad2012-07-03 14:33:25 -0700763 int i, rc, num_chans = pdata->num_channels;
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700764
Stephen Boydaeaf2ad2012-07-03 14:33:25 -0700765 for (i = 0; i < num_chans; i++) {
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700766 rc = device_create_file(&pdev->dev,
Stephen Boydaeaf2ad2012-07-03 14:33:25 -0700767 &epm_adc_in_attrs[i].dev_attr);
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700768 if (rc) {
769 dev_err(&pdev->dev, "device_create_file failed\n");
770 return rc;
771 }
772 }
773
Stephen Boydaeaf2ad2012-07-03 14:33:25 -0700774 return 0;
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700775}
776
777static int __devinit epm_adc_spi_probe(struct spi_device *spi)
778
779{
780 if (!epm_adc_drv)
781 return -ENODEV;
782 epm_adc_drv->epm_spi_client = spi;
783 epm_adc_drv->epm_spi_client->bits_per_word =
784 EPM_ADC_ADS_SPI_BITS_PER_WORD;
785
786 return 0;
787}
788
789static int __devexit epm_adc_spi_remove(struct spi_device *spi)
790{
791 epm_adc_drv->epm_spi_client = NULL;
792 return 0;
793}
794
795static struct spi_driver epm_spi_driver = {
796 .probe = epm_adc_spi_probe,
797 .remove = __devexit_p(epm_adc_spi_remove),
798 .driver = {
799 .name = EPM_ADC_DRIVER_NAME,
800 .owner = THIS_MODULE,
801 },
802};
803
Stephen Boyd58701e82012-04-25 11:48:28 -0700804static int __devinit epm_adc_probe(struct platform_device *pdev)
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700805{
806 struct epm_adc_drv *epm_adc;
807 struct epm_adc_platform_data *pdata = pdev->dev.platform_data;
808 int rc = 0;
809
810 if (!pdata) {
811 dev_err(&pdev->dev, "no platform data?\n");
812 return -EINVAL;
813 }
814
815 epm_adc = kzalloc(sizeof(struct epm_adc_drv), GFP_KERNEL);
816 if (!epm_adc) {
817 dev_err(&pdev->dev, "Unable to allocate memory\n");
818 return -ENOMEM;
819 }
820
821 platform_set_drvdata(pdev, epm_adc);
822 epm_adc_drv = epm_adc;
823 epm_adc->pdev = pdev;
824
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -0700825 epm_adc->misc.name = EPM_ADC_DRIVER_NAME;
826 epm_adc->misc.minor = MISC_DYNAMIC_MINOR;
827 epm_adc->misc.fops = &epm_adc_fops;
828
829 if (misc_register(&epm_adc->misc)) {
830 dev_err(&pdev->dev, "Unable to register misc device!\n");
831 return -EFAULT;
832 }
833
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700834 rc = epm_adc_init_hwmon(pdev, epm_adc);
835 if (rc) {
836 dev_err(&pdev->dev, "msm_adc_dev_init failed\n");
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -0700837 misc_deregister(&epm_adc->misc);
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700838 return rc;
839 }
840
841 epm_adc->hwmon = hwmon_device_register(&pdev->dev);
842 if (IS_ERR(epm_adc->hwmon)) {
843 dev_err(&pdev->dev, "hwmon_device_register failed\n");
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -0700844 misc_deregister(&epm_adc->misc);
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700845 rc = PTR_ERR(epm_adc->hwmon);
846 return rc;
847 }
848
849 mutex_init(&epm_adc->conv_lock);
850 epm_i2c_info = &pdata->epm_i2c_board_info;
851 epm_adc->bus_id = pdata->bus_id;
852 epm_gpio_expander_base_addr = pdata->gpio_expander_base_addr;
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -0700853 epm_adc_expander_register = false;
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700854 return rc;
855}
856
857static int __devexit epm_adc_remove(struct platform_device *pdev)
858{
859 struct epm_adc_drv *epm_adc = platform_get_drvdata(pdev);
860 struct epm_adc_platform_data *pdata = pdev->dev.platform_data;
861 int num_chans = pdata->num_channels;
862 int i = 0;
863
Stephen Boydaeaf2ad2012-07-03 14:33:25 -0700864 for (i = 0; i < num_chans; i++)
865 device_remove_file(&pdev->dev, &epm_adc_in_attrs[i].dev_attr);
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700866 hwmon_device_unregister(epm_adc->hwmon);
Siddartha Mohanadosseb90c922012-03-27 22:58:06 -0700867 misc_deregister(&epm_adc->misc);
Siddartha Mohanadoss53c16f92011-10-17 15:57:15 -0700868 epm_adc = NULL;
869
870 return 0;
871}
872
873static struct platform_driver epm_adc_driver = {
874 .probe = epm_adc_probe,
875 .remove = __devexit_p(epm_adc_remove),
876 .driver = {
877 .name = EPM_ADC_DRIVER_NAME,
878 .owner = THIS_MODULE,
879 },
880};
881
882static int __init epm_adc_init(void)
883{
884 int ret = 0;
885
886 ret = platform_driver_register(&epm_adc_driver);
887 if (ret) {
888 pr_err("%s: driver register failed, rc=%d\n", __func__, ret);
889 return ret;
890 }
891
892 ret = spi_register_driver(&epm_spi_driver);
893 if (ret)
894 pr_err("%s: spi register failed: rc=%d\n", __func__, ret);
895
896 return ret;
897}
898
899static void __exit epm_adc_exit(void)
900{
901 spi_unregister_driver(&epm_spi_driver);
902 platform_driver_unregister(&epm_adc_driver);
903}
904
905module_init(epm_adc_init);
906module_exit(epm_adc_exit);
907
908MODULE_DESCRIPTION("EPM ADC Driver");
909MODULE_ALIAS("platform:epm_adc");
910MODULE_LICENSE("GPL v2");