static int comp_init(struct td_device *dev) { int i; struct cmp_cb *cmp_cb_tmp = (struct cmp_cb *)dev->priv; for (i = 0; i < CMP_COUNT; i++) { cmp_cb_tmp[i].cb = NULL; cmp_cb_tmp[i].cb_data = NULL; } dev->priv = cmp_cb_tmp; #ifdef CONFIG_QUARK MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, INT_COMPARATORS_HOST_MASK) |= INT_COMPARATORS_MASK; #elif CONFIG_ARC MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, INT_COMPARATORS_SS_MASK) |= INT_COMPARATORS_MASK; #endif MMIO_REG_VAL(CMP_STAT_CLR) |= INT_COMPARATORS_MASK; MMIO_REG_VAL(CMP_EN) &= ~(INT_COMPARATORS_MASK); MMIO_REG_VAL(CMP_PWR) &= ~(INT_COMPARATORS_MASK); /* enable interrupt trap for comparator driver */ IRQ_CONNECT(SOC_CMP_INTERRUPT, ISR_DEFAULT_PRIO, comp_isr, NULL, 0); irq_enable(SOC_CMP_INTERRUPT); return 0; }
static void qrk_cxxxx_rtc_clock_frequency(uint32_t frequency) { MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_CCU_SYS_CLK_CTL_OFFSET) &= ~SCSS_CCU_RTC_CLK_DIV_EN; MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_CCU_SYS_CLK_CTL_OFFSET) &= ~SCSS_RTC_CLK_DIV_MASK; MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_CCU_SYS_CLK_CTL_OFFSET) |= frequency; MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_CCU_SYS_CLK_CTL_OFFSET) |= SCSS_CCU_RTC_CLK_DIV_EN; }
/*! \fn DRIVER_API_RC qrk_cxxxx_rtc_set_config(struct qrk_cxxxx_rtc_config *config) * * \brief Function to configure the RTC * * \param config : pointer to a RTC configuration structure * * \return DRV_RC_OK on success\n * DRV_RC_FAIL otherwise */ DRIVER_API_RC qrk_cxxxx_rtc_set_config(struct qrk_cxxxx_rtc_config *config) { OS_ERR_TYPE err; /* Set RTC divider - 32.768khz / 32768 = 1 second. * Note: Divider not implemented in standard emulation image. */ qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_1_HZ); MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) |= QRK_RTC_INTERRUPT_MASK; /* set initial RTC value */ while (config->initial_rtc_val != MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCVR)) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = config->initial_rtc_val; } pm_wakelock_acquire(&rtc_wakelock); timer_start(rtc_wakelock_timer, RTC_WAKELOCK_DELAY, &err); if(err != E_OS_OK) { pm_wakelock_release(&rtc_wakelock); return DRV_RC_BUSY; } MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_MASK; return DRV_RC_OK; }
static void i2s_dma_cb_done(void *num) { uint8_t channel = (uint32_t)num; uint32_t reg; if(channel == I2S_CHANNEL_TX) { if((0x00200000 & MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_CTRL)) && !(0x18000000 & MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_CTRL))) { for(int i = 0; i < 4; ++i) MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_DATA_REG) = 0x0; } do { reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].fifo_stat); } while(reg & 0x000000FF); } if (i2s_info->cfg[channel].cb_done) { i2s_info->cfg[channel].cb_done(i2s_info->cfg[channel].cb_done_arg); } i2s_disable(channel); return; }
void qrk_aonpt_start(void) { MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_AONPT_CTRL) = (AONPT_CLR | AONPT_RST); volatile uint32_t time = get_uptime_32k(); while(get_uptime_32k() - time < 5); MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_AONPT_STAT); }
void qrk_aonpt_stop(void) { uint32_t flags = interrupt_lock(); MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_AONPT_CFG) = 0; MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_AONPT_CTRL) = (AONPT_CLR | AONPT_RST); volatile uint32_t time = get_uptime_32k(); while(get_uptime_32k() - time < 5); interrupt_unlock(flags); }
void aonpt_ISR(void) { if (!is_oneshot) { MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE,SCSS_AONPT_CTRL) = AONPT_CLR; MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_AONPT_STAT); } if (callback_fn != NULL) callback_fn(); }
static int qrk_aonpt_resume(struct device *dev) { SET_INTERRUPT_HANDLER(SOC_AONPT_INTERRUPT, aonpt_ISR); SOC_UNMASK_INTERRUPTS(SCSS_AON_TIMER_MASK); MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_AONPT_STAT); return 0; }
/* ISR */ static void i2s_isr(void) { uint32_t stat; // Determine interrupt source stat = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_STAT); // Check for errors if (stat & (1 << SOC_I2S_STAT_TDATA_UNDERR)) { if (i2s_info->cfg[I2S_CHANNEL_TX].cb_err) { i2s_info->cfg[I2S_CHANNEL_TX].cb_err_arg=(void *)stat; i2s_info->cfg[I2S_CHANNEL_TX].cb_err(i2s_info->cfg[I2S_CHANNEL_TX].cb_err_arg); } i2s_disable(I2S_CHANNEL_TX); } if (stat & (1 << SOC_I2S_STAT_RDATA_OVRERR)) { if (i2s_info->cfg[I2S_CHANNEL_RX].cb_err) { i2s_info->cfg[I2S_CHANNEL_RX].cb_err_arg=(void *)stat; i2s_info->cfg[I2S_CHANNEL_RX].cb_err(i2s_info->cfg[I2S_CHANNEL_RX].cb_err_arg); } i2s_disable(I2S_CHANNEL_RX); } return; }
void qrk_aonpt_configure(uint32_t period, void (*on_timeout_cb)(), bool one_shot) { /* stops the previous alarm if any */ qrk_aonpt_stop(); callback_fn = on_timeout_cb; is_oneshot = one_shot; MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_AONPT_CFG) = period; }
DRIVER_API_RC qrk_cxxxx_rtc_set_alarm(struct qrk_cxxxx_rtc_alarm *alarm){ MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_ENABLE; if(false != alarm->alarm_enable) { if(alarm->callback_fn) { callback_fn = alarm->callback_fn; callback_param = alarm->callback_param; } MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_EOI); MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CMR) = alarm->alarm_rtc_val; SET_INTERRUPT_HANDLER(SOC_RTC_INTERRUPT, rtc_isr); /* unmask RTC interrupts to qrk */ MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_INT_RTC_MASK_OFFSET) = QRK_INT_RTC_UNMASK_QRK; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) |= QRK_RTC_INTERRUPT_ENABLE; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_MASK; } else { MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_INT_RTC_MASK_OFFSET) = ~(0); } pm_wakelock_release(&rtc_wakelock); pm_wakelock_acquire(&rtc_wakelock, RTC_WAKELOCK_TIMEOUT); return DRV_RC_OK; }
/*! \fn void rtc_isr(void) * * \brief RTC alarm ISR, if specified calls a user defined callback */ static void rtc_isr(void *arg) { struct device *dev = arg; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_EOI); if (callback_fn) (*callback_fn)(dev); }
/*! \fn void rtc_isr(void) * * \brief RTC alarm ISR, if specified calls a user defined callback */ void rtc_isr(void) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_EOI); if (callback_fn) { (*callback_fn)(callback_param); } }
void variantPwmInit(void) { /* Enable PWM peripheral clock */ MMIO_REG_VAL(QRK_CLKGATE_CTRL) |= QRK_CLKGATE_CTRL_PWM_ENABLE; /* Select PWM mode, with interrupts masked */ for (uint8_t i = 0; i < NUM_PWM; i++) { uint32_t offset = ((i * QRK_PWM_N_REGS_LEN) + QRK_PWM_N_CONTROL); MMIO_REG_VAL_FROM_BASE(QRK_PWM_BASE_ADDR, offset) = QRK_PWM_CONTROL_PWM_OUT | QRK_PWM_CONTROL_INT_MASK | QRK_PWM_CONTROL_MODE_PERIODIC; } }
/*! \fn int qrk_cxxxx_rtc_set_config(struct device *dev, struct rtc_config *config) * * \brief Function to configure the RTC * * \param config : pointer to a RTC configuration structure * * \return DEV_OK on success\n * DEV_USED otherwise */ static int qrk_cxxxx_rtc_set_config(struct device * rtc_dev, struct rtc_config * config) { OS_ERR_TYPE err; /* Set RTC divider - 32.768khz / 32768 = 1 second. * Note: Divider not implemented in standard emulation image. */ if (!is_rtc_init_done) { qrk_cxxxx_rtc_one_time_setup(rtc_dev); is_rtc_init_done = true; } /* Set RTC divider 1HZ */ qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_1_HZ); MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) |= QRK_RTC_INTERRUPT_MASK; if (false != config->alarm_enable) { if (config->cb_fn) callback_fn = config->cb_fn; } else { /* set initial RTC value */ while (config->init_val != MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCVR)) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = config->init_val; } MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_INT_RTC_MASK_OFFSET) = ~(0); } pm_wakelock_acquire(&rtc_wakelock); timer_start(rtc_wakelock_timer, RTC_WAKELOCK_DELAY, &err); if (err != E_OS_OK) { pm_wakelock_release(&rtc_wakelock); return DEV_USED; } MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_MASK; return DEV_OK; }
/*! \fn int qrk_cxxxx_rtc_set_alarm(struct device *rtc_dev, const uint32_t alarm_val) * * \brief Function to set an RTC alarm * * \param alarm_val Alarm value * * \return DEV_OK on success * DEV_USED otherwise */ int qrk_cxxxx_rtc_set_alarm(struct device *rtc_dev, const uint32_t alarm_val) { OS_ERR_TYPE err; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_ENABLE; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_EOI); MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CMR) = alarm_val; irq_enable(SOC_RTC_INTERRUPT); /* unmask RTC interrupts to quark */ MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_INT_RTC_MASK_OFFSET) = QRK_INT_RTC_UNMASK_QRK; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) |= QRK_RTC_INTERRUPT_ENABLE; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_MASK; pm_wakelock_acquire(&rtc_wakelock); timer_start(rtc_wakelock_timer, RTC_WAKELOCK_DELAY, &err); if (err != E_OS_OK) { pm_wakelock_release(&rtc_wakelock); return DEV_USED; } return DEV_OK; }
void set_oscillator(int internal) { if (internal) { /* Start internal oscillator (with trim) */ MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_OSC0_CFG1) |= INTERNAL_OSC_TRIM << OSC0_CFG1_INTERNAL_OSC_TRIM_BIT | OSC0_CFG1_INTERNAL_OSC_EN_MASK; /* Wait internal oscillator ready */ while (!((MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_OSC0_STAT1) & OSC0_STAT1_LOCK_INTERNAL))) ; /* Trim internal oscillator */ MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_OSC0_CFG1) = INTERNAL_OSC_TRIM << OSC0_CFG1_INTERNAL_OSC_TRIM_BIT | OSC0_CFG1_INTERNAL_OSC_EN_MASK; } else { /* Set clk to 32MHz, external oscillator, 5.5pF load */ MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_OSC0_CFG1) |= OSC0_CFG1_XTAL_OSC_TRIM_5_55_PF | OSC0_CFG1_XTAL_OSC_EN_MASK; /* Wait internal regulator ready */ while (!((MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_OSC0_STAT1) & OSC0_STAT1_LOCK_XTAL))) ; /* Switch to external oscillator */ MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_OSC0_CFG1) = OSC0_CFG1_XTAL_OSC_TRIM_5_55_PF | (OSC0_CFG1_XTAL_OSC_EN_MASK | OSC0_CFG1_XTAL_OSC_OUT_MASK); } }
static int qrk_cxxxx_rtc_init(struct device* dev) { const uint32_t expected_freq = SCSS_RTC_CLK_DIV_1_HZ | SCSS_CCU_RTC_CLK_DIV_EN; qrk_cxxxx_rtc_enable(dev); uint32_t curr_freq = MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_CCU_SYS_CLK_CTL_OFFSET) & (SCSS_CCU_RTC_CLK_DIV_EN | SCSS_RTC_CLK_DIV_MASK); pm_wakelock_init(&rtc_wakelock, RTC_WAKELOCK); // disable interrupt MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_ENABLE; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_EOI); /* Reset initial value only if RTC wasn't enabled at right frequency at * beginning of init */ if (expected_freq != curr_freq) { // Set RTC divider 4096HZ for fast uptade qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_4096_HZ); /* set intial RTC value 0 */ MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = 0; while (0 != MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCVR)) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = 0; } } // Set RTC divider 1HZ qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_1_HZ); return 0; }
DRIVER_API_RC comp_configure(struct td_device *dev, int index, int polarity, int refsel, void (*cb)(void *), void *param) { struct cmp_cb *cmp_cb_tmp = (struct cmp_cb *)dev->priv; if (index >= CMP_COUNT || index < 0) { return DRV_RC_INVALID_CONFIG; } cmp_cb_tmp[index].cb = cb; cmp_cb_tmp[index].cb_data = param; // Enable comparator <index> MMIO_REG_VAL(CMP_PWR) |= (1 << index); if (polarity) MMIO_REG_VAL(CMP_REF_POL) |= (1 << index); else MMIO_REG_VAL(CMP_REF_POL) &= ~(1 << index); if (refsel) MMIO_REG_VAL(CMP_REF_SEL) |= (1 << index); else MMIO_REG_VAL(CMP_REF_SEL) &= ~(1 << index); // Enable power in comparator <index> MMIO_REG_VAL(CMP_EN) |= (1 << index); /* Enable interrupt to host. */ #ifdef CONFIG_QUARK MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, INT_COMPARATORS_HOST_MASK) &= ~(1 << index); #elif CONFIG_ARC MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, INT_COMPARATORS_SS_MASK) &= ~(1 << index); #else #error Unknown target for comparator driver #endif return DRV_RC_OK; }
/* Driver API */ DRIVER_API_RC soc_i2s_init() { int i; uint32_t reg; // Prep info struct for (i = 0; i < I2S_NUM_CHANNELS; i++) { i2s_info->en[i] = 0; i2s_info->cfgd[i] = 0; i2s_info->cfg[i].cb_done = NULL; i2s_info->cfg[i].cb_err = NULL; } // Enable global clock, use local clock gating per channel instead set_clock_gate(i2s_info->clk_gate_info, CLK_GATE_ON); // Setup ISR (and enable) SET_INTERRUPT_HANDLER(i2s_info->int_vector, i2s_interrupt_handler); SOC_UNMASK_INTERRUPTS(i2s_info->int_mask); // Set up control register reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_CTRL); reg |= (1 << SOC_I2S_CTRL_TR_CFG_0); reg &= ~(1 << SOC_I2S_CTRL_TSYNC_LOOP_BACK); reg &= ~(1 << SOC_I2S_CTRL_RSYNC_LOOP_BACK); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_CTRL) = reg; // Set the watermark levels MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_TFIFO_CTRL) &= 0xFFFCFFFF; MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_TFIFO_CTRL) |= (I2S_TFIFO_THR << SOC_I2S_TFIFO_CTRL_TAFULL_THRS); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_RFIFO_CTRL) &= 0xFFFCFFFF; MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_RFIFO_CTRL) |= (I2S_RFIFO_THR << SOC_I2S_RFIFO_CTRL_RAFULL_THRS); // Enable global interrupt mask reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_CID_CTRL); reg |= (1 << SOC_I2S_CID_CTRL_INTREQ_MASK); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, SOC_I2S_CID_CTRL) = reg; // Initially, have all channels disabled for (i = 0; i < I2S_NUM_CHANNELS; i++) { i2s_disable(i); } return DRV_RC_OK; }
/* Internal functions */ static void i2s_enable(uint8_t channel) { uint32_t reg; // Enable local clock and interrupts reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].cid_ctrl); reg &= ~(1 << (i2s_reg_map[channel].cid_ctrl_strobe)); reg &= ~(1 << (i2s_reg_map[channel].cid_ctrl_strobe_sync)); reg |= (1 << (i2s_reg_map[channel].cid_ctrl_mask)); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].cid_ctrl) = reg; // Clear all interrupts reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].stat); reg &= ~(i2s_reg_map[channel].stat_mask); reg |= (1 << SOC_I2S_STAT_TDATA_UNDERR); reg |= (1 << SOC_I2S_STAT_RDATA_OVRERR); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].stat) = reg; // Set enabled flag for channel i2s_info->en[channel] = 1; return; }
static void i2s_disable(uint8_t channel) { uint32_t reg; uint32_t num_active; int i; // Release DMA resources if (i2s_info->en[channel]) { soc_dma_stop_transfer(&(i2s_info->dma_ch[channel])); soc_dma_release(&(i2s_info->dma_ch[channel])); soc_dma_free_list(&(i2s_info->dma_cfg[channel])); } // Clear enabled flag for channel i2s_info->en[channel] = 0; // Let the processor do whatever power down it wants num_active = 0; for (i = 0; i < I2S_NUM_CHANNELS; i++) { if (i2s_info->en[i]) { num_active++; } } // Disable channel and hold parts in reset reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].ctrl); reg &= ~(1 << (i2s_reg_map[channel].ctrl_fifo_rst)); reg &= ~(1 << (i2s_reg_map[channel].ctrl_sync_rst)); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].ctrl) = reg; // Clear all interrupts reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].stat); reg &= ~(i2s_reg_map[channel].stat_mask); reg &= ~(1 << i2s_reg_map[channel].stat_err); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].stat) = reg; // Disable local clock and interrupts reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].cid_ctrl); reg |= (1 << (i2s_reg_map[channel].cid_ctrl_strobe)); reg |= (1 << (i2s_reg_map[channel].cid_ctrl_strobe_sync)); reg &= ~(1 << (i2s_reg_map[channel].cid_ctrl_mask)); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].cid_ctrl) = reg; return; }
static void i2s_dma_cb_done(void *num) { uint8_t channel = (uint32_t)num; uint32_t reg; if(channel == I2S_CHANNEL_TX) { do { reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].fifo_stat); } while(reg & 0x000000FF); } if (i2s_info->cfg[channel].cb_done) { i2s_info->cfg[channel].cb_done(i2s_info->cfg[channel].cb_done_arg); } i2s_disable(channel); return; }
static void qrk_cxxxx_rtc_one_time_setup(struct device *rtc_dev) { OS_ERR_TYPE err; const uint32_t expected_freq = SCSS_RTC_CLK_DIV_1_HZ | SCSS_CCU_RTC_CLK_DIV_EN; qrk_cxxxx_rtc_enable(rtc_dev); rtc_wakelock_timer = timer_create(qrk_cxxxx_rtc_wakelock_timer_callback, NULL, RTC_WAKELOCK_DELAY, false, false, &err); if (E_OS_OK != err) pr_error(LOG_MODULE_DRV, "rtc_wakelock_timer err"); uint32_t curr_freq = MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_CCU_SYS_CLK_CTL_OFFSET) & (SCSS_CCU_RTC_CLK_DIV_EN | SCSS_RTC_CLK_DIV_MASK); pm_wakelock_init(&rtc_wakelock); /* disable interrupt */ MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_ENABLE; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_EOI); /* Reset initial value only if RTC wasn't enabled at right frequency at * beginning of init */ if (expected_freq != curr_freq) { /* Set RTC divider 4096HZ for fast update */ qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_4096_HZ); /* set intial RTC value 0 */ MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = 0; while (0 != MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCVR)) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = 0; } } }
/* External API */ DRIVER_API_RC soc_i2s_config(uint8_t channel, struct soc_i2s_cfg *cfg) { uint32_t reg; uint16_t sample_rate; // Check channel no in use if (channel >= I2S_NUM_CHANNELS) { return DRV_RC_FAIL; } else if (i2s_info->en[channel]) { return DRV_RC_CONTROLLER_IN_USE; } // Set master/slave reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].ctrl); reg &= ~(1 << (i2s_reg_map[channel].ctrl_ms)); reg |= (cfg->master & 0x1) << i2s_reg_map[channel].ctrl_ms; MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].ctrl) = reg; // Calculate sample_rate divider (note, acts as if resolution is always 32) sample_rate = i2s_info->clk_speed / (cfg->sample_rate * cfg->resolution * 2); // Setup resolution and sampling rate reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].srr); reg &= ~(i2s_reg_map[channel].srr_mask); reg |= (sample_rate & 0x7FF) << i2s_reg_map[channel].srr_sample_rate; reg |= ((cfg->resolution - 1) & 0x1F) << i2s_reg_map[channel].srr_resolution; MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].srr) = reg; // Setup mode reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].dev_conf); reg &= ~(i2s_reg_map[channel].dev_conf_mask); // Use sck_polar as shift amount as its the LSb of the DEV_CONF settings reg |= ((cfg->mode & 0x3F) << i2s_reg_map[channel].dev_conf_sck_polar); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].dev_conf) = reg; // Complete configuration (and set flag) i2s_info->cfg[channel] = *cfg; i2s_info->cfgd[channel] = 1; return DRV_RC_OK; }
uint32_t qrk_aonpt_read(void) { return MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_AONPT_CNT); }
/*! \fn uint32_t qrk_cxxxx_rtc_read(void) * * \brief Function to read the RTC * * \return uint32_t - epoch time */ uint32_t qrk_cxxxx_rtc_read(void) { return MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCVR); }
DRIVER_API_RC soc_i2s_stream(uint32_t *buf, uint32_t len, uint32_t num_bufs) { DRIVER_API_RC ret; uint8_t channel = I2S_CHANNEL_TX; uint32_t reg; uint32_t len_per_buf; int i; struct soc_dma_xfer_item *dma_list; // Check channel no in use and configured if (channel >= I2S_NUM_CHANNELS) { return DRV_RC_FAIL; } else if (i2s_info->en[channel] || !(i2s_info->cfgd[channel])) { return DRV_RC_FAIL; } // Get a DMA channel ret = soc_dma_acquire(&(i2s_info->dma_ch[channel])); if (ret != DRV_RC_OK) { return DRV_RC_FAIL; } // Enable the channel i2s_enable(channel); // Determine the length of a single buffer if (num_bufs == 0) { len_per_buf = len; } else { len_per_buf = len / num_bufs; } // Prep some configuration i2s_info->dma_cfg[channel].type = SOC_DMA_TYPE_MEM2PER; i2s_info->dma_cfg[channel].dest_interface = SOC_DMA_INTERFACE_I2S_TX; i2s_info->dma_cfg[channel].dest_step_count = 0; i2s_info->dma_cfg[channel].src_step_count = 0; i2s_info->dma_cfg[channel].xfer.dest.delta = SOC_DMA_DELTA_NONE; i2s_info->dma_cfg[channel].xfer.dest.width = SOC_DMA_WIDTH_32; i2s_info->dma_cfg[channel].xfer.dest.addr = (void *)(SOC_I2S_BASE + SOC_I2S_DATA_REG); i2s_info->dma_cfg[channel].xfer.src.delta = SOC_DMA_DELTA_INCR; i2s_info->dma_cfg[channel].xfer.src.width = SOC_DMA_WIDTH_32; if (num_bufs == 0) { i2s_info->dma_cfg[channel].cb_done = i2s_dma_cb_done; i2s_info->dma_cfg[channel].cb_done_arg = (void *)((uint32_t)channel); } else { i2s_info->dma_cfg[channel].cb_block = i2s_dma_cb_block; i2s_info->dma_cfg[channel].cb_block_arg = (void *)((uint32_t)channel); } i2s_info->dma_cfg[channel].cb_err = i2s_dma_cb_err; i2s_info->dma_cfg[channel].cb_err_arg = (void *)((uint32_t)channel); // Setup the linked list for (i = 0; i < ((num_bufs == 0) ? 1 : num_bufs); i++) { if (i == 0) { dma_list = &(i2s_info->dma_cfg[channel].xfer); } else { ret = soc_dma_alloc_list_item(&dma_list, dma_list); if (ret != DRV_RC_OK) { goto fail; } } dma_list->src.addr = (void *)(&(buf[i * (len_per_buf / sizeof(uint32_t))])); dma_list->size = len_per_buf / sizeof(uint32_t); } // Create a circular list if we are doing circular buffering if (num_bufs != 0) { dma_list->next = &(i2s_info->dma_cfg[channel].xfer); } // Setup and start the DMA engine ret = soc_dma_config(&(i2s_info->dma_ch[channel]), &(i2s_info->dma_cfg[channel])); if (ret != DRV_RC_OK) { goto fail; } ret = soc_dma_start_transfer(&(i2s_info->dma_ch[channel])); if (ret != DRV_RC_OK) { goto fail; } // Enable the channel and let it go! reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].ctrl); reg |= (1 << (i2s_reg_map[channel].ctrl_en)); reg |= (1 << (i2s_reg_map[channel].ctrl_sync_rst)); MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].ctrl) = reg; return DRV_RC_OK; fail: i2s_disable(channel); soc_dma_release(&(i2s_info->dma_ch[channel])); return DRV_RC_FAIL; }
/*! \fn void qrk_cxxxx_rtc_clk_disable(void) * * \brief Function to disable RTC clock */ void qrk_cxxxx_rtc_clk_disable(void) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_ENABLE; }
void run_arc_driver_tests(void) { // Disable all interrupts on QRK core MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, INT_SPI_MST_0_MASK) |= ~(QRK_INT_UNMASK_IA); MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, INT_SPI_MST_1_MASK) |= ~(QRK_INT_UNMASK_IA); MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, INT_I2C_MST_0_MASK) |= ~(QRK_INT_UNMASK_IA); MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, INT_I2C_MST_1_MASK) |= ~(QRK_INT_UNMASK_IA); cu_set_log_backend(&log_backend_os_printk); #if defined (CONFIG_SS_ADC) CU_RUN_TEST(adc_test); #endif CU_RUN_TEST(cbuffer_tst); /* TODO: drop when KConfig implemented*/ #if defined (CONFIG_BOARD_CURIE_APP) && defined (CONFIG_SBA) && defined (CONFIG_INTEL_QRK_SPI) CU_RUN_TEST(sba_spi_test); //ARC SBA SOC SPI test #endif #if defined (CONFIG_BOARD_CURIE_APP) && defined (CONFIG_SBA) && defined (CONFIG_SPI) CU_RUN_TEST(sba_ss_unit_spi); //ARC SBA SS SPI test #endif #if defined (CONFIG_BOARD_CURIE_APP) && defined (CONFIG_SBA) && defined (CONFIG_INTEL_QRK_I2C) CU_RUN_TEST(sba_i2c_test); //ARC SBA SOC I2C test #endif #if defined (CONFIG_BOARD_CURIE_APP) && defined (CONFIG_SBA) && defined (CONFIG_I2C) CU_RUN_TEST(sba_ss_unit_i2c); #endif #if defined (CONFIG_GPIO_DRIVER_TESTS) #if defined (CONFIG_SOC_GPIO_32) CU_RUN_TEST(gpio_test); #endif #if defined (CONFIG_SOC_GPIO_AON) CU_RUN_TEST(gpio_aon_test); #endif #if defined (CONFIG_SS_GPIO) CU_RUN_TEST(gpio_ss_test); #endif #endif #ifdef CONFIG_SOC_COMPARATOR CU_RUN_TEST(comparator_test); #endif CU_RUN_TEST(wakelock_test); #if defined (CONFIG_BMI160) CU_RUN_TEST(bmi160_unit_test); #endif #if defined (CONFIG_BME280) CU_RUN_TEST(bme280_unit_test); #endif }