/* When the calibration overflows, it means the fine trim code * has reached 0x1F, but the clock is still too fast. Thus, * software must increase the coarse trim code by 1 */ static void timer_sof_calibration_overflow_int(void) { unsigned coarseTrimValue = GREG32(XO, CLK_TIMER_RC_COARSE_ATE_TRIM); unsigned max; CPRINTS("%s: 0x%02x", __func__, coarseTrimValue); if (GREAD_FIELD(XO, CLK_TIMER_CALIB_TRIM_CTRL, MAX_TRIM_SEL)) max = 0x1f; else max = 0xff; if (coarseTrimValue < max) GREG32(XO, CLK_TIMER_RC_COARSE_ATE_TRIM) = coarseTrimValue + 1; GREG32(XO, DXO_INT_STATE) = GC_XO_DXO_INT_STATE_SLOW_CALIB_OVERFLOW_MASK; }
/* * Push data to the SPS TX FIFO * @param data Pointer to 8-bit data * @param data_size Number of bytes to transmit * @return : actual number of bytes placed into tx fifo */ int sps_transmit(uint8_t *data, size_t data_size) { volatile uint32_t *sps_tx_fifo; uint32_t rptr; uint32_t wptr; uint32_t fifo_room; int bytes_sent; int inst = 0; if (GREAD_FIELD_I(SPS, inst, ISTATE, TXFIFO_EMPTY)) tx_empty_count++; /* Inside packet this means underrun. */ sps_tx_fifo = (volatile uint32_t *)SPS_TX_FIFO_BASE_ADDR; wptr = GREG32_I(SPS, inst, TXFIFO_WPTR); rptr = GREG32_I(SPS, inst, TXFIFO_RPTR); fifo_room = (rptr - wptr - 1) & SPS_FIFO_MASK; if (fifo_room < data_size) { bytes_sent = fifo_room; data_size = fifo_room; } else { bytes_sent = data_size; } sps_tx_fifo += (wptr & SPS_FIFO_MASK) / sizeof(*sps_tx_fifo); while (data_size) { if ((wptr & 3) || (data_size < 4) || ((uintptr_t)data & 3)) { /* * Either we have less then 4 bytes to send, or one of * the pointers is not 4 byte aligned. Need to go byte * by byte. */ uint32_t fifo_contents; int bit_shift; fifo_contents = *sps_tx_fifo; do { /* * CR50 SPS controller does not allow byte * accesses for writes into the FIFO, so read * modify/write is requred. Tracked uder * http://b/20894727 */ bit_shift = 8 * (wptr & 3); fifo_contents &= ~(0xff << bit_shift); fifo_contents |= (((uint32_t)(*data++)) << bit_shift); data_size--; wptr++; } while (data_size && (wptr & 3)); *sps_tx_fifo++ = fifo_contents; } else { /* * Both fifo wptr and data are aligned and there is * plenty to send. */ *sps_tx_fifo++ = *((uint32_t *)data); data += 4; data_size -= 4; wptr += 4; } GREG32_I(SPS, inst, TXFIFO_WPTR) = wptr & SPS_FIFO_PTR_MASK; /* Make sure FIFO pointer wraps along with the index. */ if (!(wptr & SPS_FIFO_MASK)) sps_tx_fifo = (volatile uint32_t *) SPS_TX_FIFO_BASE_ADDR; } /* * Start TX if necessary. This happens after FIFO is primed, which * helps aleviate TX underrun problems but introduces delay before * data starts coming out. */ if (!GREAD_FIELD(SPS, FIFO_CTRL, TXFIFO_EN)) GWRITE_FIELD(SPS, FIFO_CTRL, TXFIFO_EN, 1); sps_tx_count += bytes_sent; return bytes_sent; }