12 #define FIFO_INTERRUPT_THRESHOLD (16)
14 #define QM_SS_ADC_CHAN_SEQ_MAX (32)
15 #define ADC_SAMPLE_SHIFT (11)
18 #define QM_SS_ADC_CMD_START_CAL (3)
19 #define QM_SS_ADC_CMD_LOAD_CAL (4)
22 #define CALCULATE_DELAY() (clk_sys_get_ticks_per_us() * 5)
24 static uint32_t adc_base[QM_SS_ADC_NUM] = {QM_SS_ADC_BASE};
27 static uint8_t sample_window[QM_SS_ADC_NUM];
30 static uint32_t count[QM_SS_ADC_NUM];
32 static void (*mode_callback[QM_SS_ADC_NUM])(
void *data,
int error,
35 static void (*cal_callback[QM_SS_ADC_NUM])(
void *data,
int error,
38 static void *mode_callback_data[QM_SS_ADC_NUM];
39 static void *cal_callback_data[QM_SS_ADC_NUM];
41 static void dummy_conversion(uint32_t controller);
46 static volatile bool ignore_spurious_interrupt[QM_SS_ADC_NUM] = {
true};
49 static void enable_adc(
void)
52 QM_SS_ADC_CTRL_ADC_ENA);
55 static void disable_adc(
void)
58 QM_SS_ADC_CTRL_ADC_ENA);
61 static void qm_ss_adc_isr_handler(
const qm_ss_adc_t adc)
63 uint32_t i, samples_to_read;
64 uint32_t controller = adc_base[adc];
67 samples_to_read = FIFO_INTERRUPT_THRESHOLD;
68 if (samples_to_read > (irq_xfer[adc]->samples_len - count[adc])) {
69 samples_to_read = irq_xfer[adc]->
samples_len - count[adc];
73 for (i = 0; i < samples_to_read; i++) {
76 QM_SS_ADC_SET_POP_RX);
78 irq_xfer[adc]->
samples[count[adc]] =
80 (ADC_SAMPLE_SHIFT - resolution[adc]));
85 QM_SS_ADC_CTRL_CLR_DATA_A);
87 if (count[adc] == irq_xfer[adc]->samples_len) {
90 QM_SS_ADC_CTRL_SEQ_START);
94 QM_SS_ADC_CTRL_MSK_ALL_INT);
97 if (irq_xfer[adc]->callback) {
98 irq_xfer[adc]->
callback(irq_xfer[adc]->callback_data, 0,
110 static void qm_ss_adc_isr_err_handler(
const qm_ss_adc_t adc)
112 uint32_t controller = adc_base[adc];
117 QM_SS_ADC_CTRL_SEQ_START);
121 QM_SS_ADC_CTRL_MSK_ALL_INT);
124 if (intstat & QM_SS_ADC_INTSTAT_OVERFLOW) {
125 if (irq_xfer[adc]->callback) {
126 irq_xfer[adc]->
callback(irq_xfer[adc]->callback_data,
131 if (intstat & QM_SS_ADC_INTSTAT_UNDERFLOW) {
132 if (irq_xfer[adc]->callback) {
133 irq_xfer[adc]->
callback(irq_xfer[adc]->callback_data,
138 if (intstat & QM_SS_ADC_INTSTAT_SEQERROR) {
139 if (irq_xfer[adc]->callback) {
140 irq_xfer[adc]->
callback(irq_xfer[adc]->callback_data,
148 (QM_SS_ADC_CTRL_CLR_SEQERROR |
149 QM_SS_ADC_CTRL_CLR_OVERFLOW |
150 QM_SS_ADC_CTRL_CLR_UNDERFLOW));
156 static void qm_ss_adc_isr_pwr_handler(
const qm_ss_adc_t adc)
158 uint32_t controller = adc_base[adc];
163 if (ignore_spurious_interrupt[adc]) {
164 ignore_spurious_interrupt[adc] =
false;
170 dummy_conversion(controller);
174 if (mode_callback[adc]) {
180 static void qm_ss_adc_isr_cal_handler(
const qm_ss_adc_t adc)
184 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ);
187 if (cal_callback[adc]) {
223 uint32_t i, reg, ch_odd, ch_even, seq_entry = 0;
224 uint32_t num_channels, controller = adc_base[adc];
228 uint16_t delay = (sample_window[adc] - (resolution[adc] + 3));
232 QM_SS_ADC_CTRL_SEQ_TABLE_RST);
242 for (i = 0; i < (num_channels - 1); i += 2) {
243 ch_odd = xfer->
ch[(i + 1) % xfer->
ch_len];
244 ch_even = xfer->
ch[i % xfer->
ch_len];
246 ((delay << QM_SS_ADC_SEQ_DELAYODD_OFFSET) |
247 (ch_odd << QM_SS_ADC_SEQ_MUXODD_OFFSET) |
248 (delay << QM_SS_ADC_SEQ_DELAYEVEN_OFFSET) | ch_even);
253 if (num_channels % 2) {
254 ch_even = xfer->
ch[i % xfer->
ch_len];
256 ((delay << QM_SS_ADC_SEQ_DELAYEVEN_OFFSET) | (ch_even));
262 QM_SS_ADC_CTRL_SEQ_PTR_RST);
266 reg &= ~QM_SS_ADC_SET_SEQ_ENTRIES_MASK;
267 reg |= ((num_channels - 1) << QM_SS_ADC_SET_SEQ_ENTRIES_OFFSET);
271 static void dummy_conversion(uint32_t controller)
277 QM_SS_REG_AUX_OR(controller +
QM_SS_ADC_SET, QM_SS_ADC_SET_FLUSH_RX);
281 QM_SS_ADC_CTRL_SEQ_TABLE_RST);
284 __builtin_arc_sr(QM_SS_ADC_SEQ_DUMMY, controller +
QM_SS_ADC_SEQ);
288 QM_SS_ADC_CTRL_SEQ_PTR_RST);
292 reg &= ~QM_SS_ADC_SET_SEQ_ENTRIES_MASK;
293 reg |= (0 << QM_SS_ADC_SET_SEQ_ENTRIES_OFFSET);
298 reg &= ~QM_SS_ADC_SET_THRESHOLD_MASK;
299 reg |= (0 << QM_SS_ADC_SET_THRESHOLD_OFFSET);
303 QM_SS_REG_AUX_NAND(controller +
QM_SS_ADC_SET, QM_SS_ADC_SET_SEQ_MODE);
307 QM_SS_ADC_CTRL_CLR_ALL_INT);
310 QM_SS_ADC_CTRL_MSK_ALL_INT);
316 QM_SS_REG_AUX_OR(controller +
QM_SS_ADC_CTRL, QM_SS_ADC_CTRL_SEQ_START);
323 QM_SS_REG_AUX_OR(controller +
QM_SS_ADC_SET, QM_SS_ADC_SET_FLUSH_RX);
326 QM_SS_ADC_CTRL_CLR_DATA_A);
330 QM_SS_ADC_CTRL_MSK_ALL_INT);
339 uint32_t controller = adc_base[adc];
341 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
342 QM_CHECK(NULL != cfg, -EINVAL);
349 sample_window[adc] = cfg->
window;
354 reg &= ~QM_SS_ADC_SET_SAMPLE_WIDTH_MASK;
355 reg |= resolution[adc];
363 uint32_t creg, delay, intstat;
364 uint32_t controller = adc_base[adc];
366 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
370 intstat = QM_IR_GET_MASK(QM_INTERRUPT_ROUTER->adc_0_pwr_int_mask);
372 QM_IR_MASK_INTERRUPTS(QM_INTERRUPT_ROUTER->adc_0_pwr_int_mask);
375 delay = CALCULATE_DELAY();
379 creg &= ~((QM_SS_IO_CREG_MST0_CTRL_ADC_DELAY_MASK
380 << QM_SS_IO_CREG_MST0_CTRL_ADC_DELAY_OFFSET) |
381 QM_SS_IO_CREG_MST0_CTRL_ADC_PWR_MODE_MASK);
382 creg |= ((delay << QM_SS_IO_CREG_MST0_CTRL_ADC_DELAY_OFFSET) | mode);
387 QM_SS_IO_CREG_SLV0_OBSR_ADC_PWR_MODE_STS)) {
392 ignore_spurious_interrupt[adc] =
true;
393 QM_IR_UNMASK_INTERRUPTS(
394 QM_INTERRUPT_ROUTER->adc_0_pwr_int_mask);
399 dummy_conversion(controller);
406 void (*callback)(
void *data,
int error,
411 uint32_t creg, delay;
412 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
415 mode_callback[adc] = callback;
416 mode_callback_data[adc] = callback_data;
417 requested_mode[adc] = mode;
420 delay = CALCULATE_DELAY();
424 creg &= ~((QM_SS_IO_CREG_MST0_CTRL_ADC_DELAY_MASK
425 << QM_SS_IO_CREG_MST0_CTRL_ADC_DELAY_OFFSET) |
426 QM_SS_IO_CREG_MST0_CTRL_ADC_PWR_MODE_MASK);
427 creg |= ((delay << QM_SS_IO_CREG_MST0_CTRL_ADC_DELAY_OFFSET) | mode);
435 uint32_t creg, intstat;
436 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
439 intstat = QM_IR_GET_MASK(QM_INTERRUPT_ROUTER->adc_0_cal_int_mask);
441 QM_IR_MASK_INTERRUPTS(QM_INTERRUPT_ROUTER->adc_0_cal_int_mask);
448 creg &= ~(QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_CMD_MASK |
449 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ);
450 creg |= ((QM_SS_ADC_CMD_START_CAL
451 << QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_CMD_OFFSET) |
452 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ);
457 QM_SS_IO_CREG_SLV0_OBSR_ADC_CAL_ACK)) {
462 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ);
464 QM_SS_IO_CREG_SLV0_OBSR_ADC_CAL_ACK) {
472 QM_IR_UNMASK_INTERRUPTS(
473 QM_INTERRUPT_ROUTER->adc_0_cal_int_mask);
480 void (*callback)(
void *data,
int error,
486 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
488 cal_callback[adc] = callback;
489 cal_callback_data[adc] = callback_data;
496 creg &= ~(QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_CMD_MASK |
497 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ);
498 creg |= ((QM_SS_ADC_CMD_START_CAL
499 << QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_CMD_OFFSET) |
500 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ);
509 uint32_t creg, intstat;
511 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
512 QM_CHECK(cal_data <= QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_VAL_MAX, -EINVAL);
515 intstat = QM_IR_GET_MASK(QM_INTERRUPT_ROUTER->adc_0_cal_int_mask);
517 QM_IR_MASK_INTERRUPTS(QM_INTERRUPT_ROUTER->adc_0_cal_int_mask);
521 creg &= ~(QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_VAL_MASK |
522 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_CMD_MASK |
523 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ);
524 creg |= ((cal_data << QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_VAL_OFFSET) |
525 (QM_SS_ADC_CMD_LOAD_CAL
526 << QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_CMD_OFFSET) |
527 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ);
532 QM_SS_IO_CREG_SLV0_OBSR_ADC_CAL_ACK)) {
537 QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ);
539 QM_SS_IO_CREG_SLV0_OBSR_ADC_CAL_ACK) {
544 QM_IR_UNMASK_INTERRUPTS(
545 QM_INTERRUPT_ROUTER->adc_0_cal_int_mask);
554 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
555 QM_CHECK(NULL != cal, -EINVAL);
558 QM_SS_IO_CREG_SLV0_OBSR_ADC_CAL_VAL_MASK) >>
559 QM_SS_IO_CREG_SLV0_OBSR_ADC_CAL_VAL_OFFSET);
568 uint32_t controller = adc_base[adc];
571 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
572 QM_CHECK(NULL != xfer, -EINVAL);
573 QM_CHECK(NULL != xfer->
ch, -EINVAL);
574 QM_CHECK(NULL != xfer->
samples, -EINVAL);
575 QM_CHECK(xfer->
ch_len > 0, -EINVAL);
576 QM_CHECK(xfer->
ch_len <= QM_SS_ADC_CHAN_SEQ_MAX, -EINVAL);
578 QM_CHECK(xfer->
samples_len <= QM_SS_ADC_FIFO_LEN, -EINVAL);
581 QM_SS_REG_AUX_OR(controller +
QM_SS_ADC_SET, QM_SS_ADC_SET_FLUSH_RX);
584 setup_seq_table(adc, xfer,
true);
588 reg &= ~QM_SS_ADC_SET_THRESHOLD_MASK;
589 reg |= ((xfer->
samples_len - 1) << QM_SS_ADC_SET_THRESHOLD_OFFSET);
593 QM_SS_REG_AUX_NAND(controller +
QM_SS_ADC_SET, QM_SS_ADC_SET_SEQ_MODE);
597 QM_SS_ADC_CTRL_MSK_ALL_INT);
603 QM_SS_REG_AUX_OR(controller +
QM_SS_ADC_CTRL, QM_SS_ADC_CTRL_SEQ_START);
621 QM_SS_ADC_SET_POP_RX);
625 (ADC_SAMPLE_SHIFT - resolution[adc]));
630 QM_SS_ADC_CTRL_CLR_DATA_A);
641 uint32_t controller = adc_base[adc];
643 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
644 QM_CHECK(NULL != xfer, -EINVAL);
645 QM_CHECK(NULL != xfer->
ch, -EINVAL);
646 QM_CHECK(NULL != xfer->
samples, -EINVAL);
647 QM_CHECK(xfer->
ch_len > 0, -EINVAL);
649 QM_CHECK(xfer->
ch_len <= QM_SS_ADC_CHAN_SEQ_MAX, -EINVAL);
652 QM_SS_REG_AUX_OR(controller +
QM_SS_ADC_SET, QM_SS_ADC_SET_FLUSH_RX);
655 setup_seq_table(adc, xfer,
false);
658 irq_xfer[adc] = xfer;
665 reg &= ~QM_SS_ADC_SET_THRESHOLD_MASK;
666 reg |= (FIFO_INTERRUPT_THRESHOLD - 1) << QM_SS_ADC_SET_THRESHOLD_OFFSET;
670 QM_SS_REG_AUX_OR(controller +
QM_SS_ADC_SET, QM_SS_ADC_SET_SEQ_MODE);
679 QM_SS_REG_AUX_OR(controller +
QM_SS_ADC_CTRL, QM_SS_ADC_CTRL_SEQ_START);
684 #if (ENABLE_RESTORE_CONTEXT)
688 const uint32_t controller = adc_base[adc];
690 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
691 QM_CHECK(NULL != ctx, -EINVAL);
699 ~QM_SS_ADC_CTRL_ADC_ENA;
707 ignore_spurious_interrupt[adc] =
true;
715 const uint32_t controller = adc_base[adc];
717 QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
718 QM_CHECK(NULL != ctx, -EINVAL);
uint32_t samples_len
Length of sample array.
ADC sequence entry register.
int qm_ss_adc_convert(const qm_ss_adc_t adc, qm_ss_adc_xfer_t *xfer, qm_ss_adc_status_t *const status)
Synchronously read values from the ADC.
Calibration complete callback.
qm_ss_adc_cb_source_t
SS ADC interrupt callback source.
uint32_t adc_ctrl
ADC control.
Transfer complete or error callback.
qm_ss_adc_status_t
SS ADC status.
qm_ss_adc_resolution_t
SS ADC resolution type.
ADC clock and sequencer status register.
void(* callback)(void *data, int error, qm_ss_adc_status_t status, qm_ss_adc_cb_source_t source)
Transfer callback.
int qm_ss_adc_irq_set_mode(const qm_ss_adc_t adc, const qm_ss_adc_mode_t mode, void(*callback)(void *data, int error, qm_ss_adc_status_t status, qm_ss_adc_cb_source_t source), void *callback_data)
Switch operating mode of SS ADC.
int qm_ss_adc_irq_convert(const qm_ss_adc_t adc, qm_ss_adc_xfer_t *xfer)
Asynchronously read values from the SS ADC.
int qm_ss_adc_set_mode(const qm_ss_adc_t adc, const qm_ss_adc_mode_t mode)
Switch operating mode of SS ADC.
Normal mode, no calibration.
qm_ss_adc_channel_t * ch
Channel sequence array (1-32 channels).
Mode change complete callback.
qm_ss_adc_mode_t
SS ADC operating mode type.
qm_ss_adc_sample_t * samples
Array to store samples.
qm_ss_adc_t
Sensor Subsystem ADC.
ADC and sequencer settings register.
ADC interrupt status register.
int qm_ss_adc_get_calibration(const qm_ss_adc_t adc, qm_ss_adc_calibration_t *const cal)
Get the current calibration data for an SS ADC.
uint8_t window
Sample interval in ADC clock cycles, defines the period to wait between the start of each sample and ...
QM_ISR_DECLARE(qm_ss_adc_0_isr)
ISR for ADC interrupt.
int qm_ss_adc_restore_context(const qm_ss_adc_t adc, const qm_ss_adc_context_t *const ctx)
Restore SS ADC context.
SS ADC configuration type.
uint32_t adc_set
ADC settings.
int qm_ss_adc_set_calibration(const qm_ss_adc_t adc, const qm_ss_adc_calibration_t cal)
Set SS ADC calibration data.
uint32_t adc_seq
ADC sequencer entry.
int qm_ss_adc_save_context(const qm_ss_adc_t adc, qm_ss_adc_context_t *const ctx)
Save SS ADC context.
int qm_ss_adc_irq_calibrate(const qm_ss_adc_t adc, void(*callback)(void *data, int error, qm_ss_adc_status_t status, qm_ss_adc_cb_source_t source), void *callback_data)
Calibrate the SS ADC.
uint8_t ch_len
Number of channels in the above array.
int qm_ss_adc_calibrate(const qm_ss_adc_t adc)
Calibrate the SS ADC.
Normal mode, with calibration.
int qm_ss_adc_set_config(const qm_ss_adc_t adc, const qm_ss_adc_config_t *const cfg)
Set SS ADC configuration.
uint32_t adc_divseqstat
ADC clock divider and sequencer status.
qm_ss_adc_resolution_t resolution
12, 10, 8, 6-bit resolution.
uint8_t qm_ss_adc_calibration_t
SS ADC calibration type.