/* adc-ti-adc108s102.c - TI's ADC 108s102 driver implementation */ /* * Copyright (c) 2015 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #define SYS_LOG_LEVEL CONFIG_SYS_LOG_ADC_LEVEL #include #include #include #include "adc_ti_adc108s102.h" static inline int _ti_adc108s102_sampling(struct device *dev) { struct ti_adc108s102_data *adc = dev->driver_data; const struct spi_buf tx_buf = { .buf = adc->cmd_buffer, .len = ADC108S102_CMD_BUFFER_SIZE }; const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 }; const struct spi_buf rx_buf = { .buf = adc->sampling_buffer, .len = ADC108S102_SAMPLING_BUFFER_SIZE }; const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1 }; SYS_LOG_DBG("Sampling!"); return spi_transceive(adc->spi, &adc->spi_cfg, &tx, &rx); } static inline void _ti_adc108s102_handle_result(struct device *dev) { struct ti_adc108s102_data *adc = dev->driver_data; struct adc_seq_table *seq_table = adc->seq_table; struct ti_adc108s102_chan *chan; struct adc_seq_entry *entry; u32_t s_i, i; SYS_LOG_DBG("_ti_adc108s102_handle_result()"); for (i = 0, s_i = 1; i < seq_table->num_entries; i++, s_i++) { entry = &seq_table->entries[i]; chan = &adc->chans[entry->channel_id]; if (entry->buffer_length - chan->buf_idx == 0) { continue; } *((u16_t *)(entry->buffer+chan->buf_idx)) = ADC108S102_RESULT(adc->sampling_buffer[s_i]); chan->buf_idx += 2; } } static inline s32_t _ti_adc108s102_prepare(struct device *dev) { struct ti_adc108s102_data *adc = dev->driver_data; struct adc_seq_table *seq_table = adc->seq_table; struct ti_adc108s102_chan *chan; s32_t sampling_delay = 0; u32_t i; adc->cmd_buf_len = 0; adc->sampling_buf_len = 1; /* Counting the dummy byte */ for (i = 0; i < seq_table->num_entries; i++) { struct adc_seq_entry *entry = &seq_table->entries[i]; /* No more space in the buffer? */ chan = &adc->chans[entry->channel_id]; if (entry->buffer_length - chan->buf_idx == 0) { continue; } SYS_LOG_DBG("Requesting channel %d", entry->channel_id); adc->cmd_buffer[adc->cmd_buf_len] = ADC108S102_CHANNEL_CMD(entry->channel_id); adc->cmd_buf_len++; adc->sampling_buf_len++; sampling_delay = entry->sampling_delay; } if (adc->cmd_buf_len == 0) { return ADC108S102_DONE; } /* dummy cmd byte */ adc->cmd_buffer[adc->cmd_buf_len] = 0; adc->cmd_buf_len++; SYS_LOG_DBG("ADC108S102 is prepared..."); return sampling_delay; } static void ti_adc108s102_enable(struct device *dev) { ARG_UNUSED(dev); /* * There is nothing to be done. If there is no sampling going on, * the chip will put itself on power-saving mode (that is because * SPI will release CS) */ } static void ti_adc108s102_disable(struct device *dev) { ARG_UNUSED(dev); /* Same issue as with ti_adc108s102_enable() */ } static inline int _verify_entries(struct adc_seq_table *seq_table) { struct adc_seq_entry *entry; u32_t chans_set = 0; int i; if (seq_table->num_entries >= ADC108S102_CMD_BUFFER_SIZE) { return 0; } for (i = 0; i < seq_table->num_entries; i++) { entry = &seq_table->entries[i]; if (entry->sampling_delay <= 0 || entry->channel_id >= ADC108S102_CHANNELS) { return 0; } if (!entry->buffer_length) { continue; } if (entry->buffer_length & 0x1) { return 0; } chans_set++; } return chans_set; } static int ti_adc108s102_read(struct device *dev, struct adc_seq_table *seq_table) { struct ti_adc108s102_data *adc = dev->driver_data; int ret = 0; s32_t delay; /* Resetting all internal channel data */ memset(adc->chans, 0, ADC108S102_CHANNELS_SIZE); if (_verify_entries(seq_table) == 0) { return -EINVAL; } adc->seq_table = seq_table; /* Sampling */ while (1) { delay = _ti_adc108s102_prepare(dev); if (delay == ADC108S102_DONE) { break; } /* convert to milliseconds */ delay = (s32_t)((MSEC_PER_SEC * (u64_t)delay) / sys_clock_ticks_per_sec); k_sleep(delay); ret = _ti_adc108s102_sampling(dev); if (ret != 0) { break; } _ti_adc108s102_handle_result(dev); } return ret; } static const struct adc_driver_api ti_adc108s102_api = { .enable = ti_adc108s102_enable, .disable = ti_adc108s102_disable, .read = ti_adc108s102_read, }; static int ti_adc108s102_init(struct device *dev) { struct ti_adc108s102_data *adc = dev->driver_data; adc->spi = device_get_binding( CONFIG_ADC_TI_ADC108S102_SPI_PORT_NAME); if (!adc->spi) { return -EINVAL; } adc->spi_cfg.operation = SPI_WORD_SET(16); adc->spi_cfg.frequency = CONFIG_ADC_TI_ADC108S102_SPI_FREQ; adc->spi_cfg.slave = CONFIG_ADC_TI_ADC108S102_SPI_SLAVE; SYS_LOG_DBG("ADC108s102 initialized"); dev->driver_api = &ti_adc108s102_api; return 0; } #ifdef CONFIG_ADC_TI_ADC108S102 static struct ti_adc108s102_data adc108s102_data; DEVICE_INIT(adc108s102, CONFIG_ADC_0_NAME, ti_adc108s102_init, &adc108s102_data, NULL, POST_KERNEL, CONFIG_ADC_INIT_PRIORITY); #endif /* CONFIG_ADC_TI_ADC108S102 */