/** * @brief SPI module data pull (read) operation. * @param dev Pointer to the device structure for the driver instance * @return None. */ static void spi_k64_pull_data(struct device *dev) { struct spi_k64_config *info = dev->config->config_info; struct spi_k64_data *spi_data = dev->driver_data; uint16_t data; #ifdef CONFIG_SPI_DEBUG uint32_t cnt = 0; /* # of bytes pulled */ #endif DBG("spi_k64_pull_data - "); do { /* initial status already checked by spi_k64_isr() */ if (spi_data->rx_buf && spi_data->rx_buf_len > 0) { data = (uint16_t)sys_read32(info->regs + SPI_K64_REG_POPR); if (spi_data->frame_sz > CHAR_BIT) { /* store 2nd byte with frame sizes larger than 8 bits */ *((uint16_t *)(spi_data->rx_buf)) = data; spi_data->rx_buf += 2; spi_data->rx_buf_len -= 2; #ifdef CONFIG_SPI_DEBUG cnt+=2; #endif } else { *(spi_data->rx_buf) = (uint8_t)data; spi_data->rx_buf++; spi_data->rx_buf_len--; #ifdef CONFIG_SPI_DEBUG cnt++; #endif } /* Clear interrupt */ sys_write32(SPI_K64_SR_RFDF, (info->regs + SPI_K64_REG_SR)); } else { /* No buffer to store data to */ break; } } while (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_RFDF); DBG("pulled: %d\n", cnt); }
ssize_t _impl_hwinfo_get_device_id(u8_t *buffer, size_t length) { uint32_t fuse_rdata[] = { sys_read32(EFUSE_BLK0_RDATA1_REG), sys_read32(EFUSE_BLK0_RDATA2_REG), }; if (length > sizeof(fuse_rdata)) { length = sizeof(fuse_rdata); } memcpy(buffer, fuse_rdata, length); return length; }
/** * @brief SPI module interrupt handler. * @param arg Pointer to the device structure for the driver instance * @return None. */ void spi_k64_isr(void *arg) { struct device *dev = arg; struct spi_k64_config *info = dev->config->config_info; uint32_t error = 0; uint32_t status; status = sys_read32(info->regs + SPI_K64_REG_SR); DBG("spi_k64_isr: dev %p, status 0x%x\n", dev, status); if (status & (SPI_K64_SR_RFOF | SPI_K64_SR_TFUF)) { /* Unrecoverable error: Rx overflow, Tx underflow */ error = 1; } else { if (status & SPI_K64_SR_TFFF) { spi_k64_push_data(dev); } if (status & SPI_K64_SR_RFDF) { spi_k64_pull_data(dev); } } /* finish processing, if data transfer is complete */ spi_k64_complete(dev, error); }
void _arch_irq_disable(unsigned int irq) { if (irq == CONFIG_MVIC_TIMER_IRQ) { sys_write32(sys_read32(MVIC_LVTTIMER) | MVIC_LVTTIMER_MASK, MVIC_LVTTIMER); } else { _mvic_rte_update(irq, MVIC_IOWIN_MASK, MVIC_IOWIN_MASK); } }
/** * @brief Find the currently executing interrupt vector, if any * * This routine finds the vector of the interrupt that is being processed. * The ISR (In-Service Register) register contain the vectors of the interrupts * in service. And the higher vector is the identification of the interrupt * being currently processed. * * MVIC ISR registers' offsets: * -------------------- * | Offset | bits | * -------------------- * | 0110H | 32:63 | * -------------------- * * @return The vector of the interrupt that is currently being processed, or * -1 if this can't be determined */ int __irq_controller_isr_vector_get(void) { /* In-service register value */ int isr; isr = sys_read32(MVIC_ISR); if (unlikely(!isr)) { return -1; } return 32 + (find_msb_set(isr) - 1); }
/* Setup power and clock for needed hardware modules. */ static void setup_modules_prcm(void) { #if defined(CONFIG_GPIO_CC2650) || \ defined(CONFIG_SERIAL) /* Setup power */ #if defined(CONFIG_GPIO_CC2650) sys_set_bit(pdctl0, CC2650_PRCM_PDCTL0_PERIPH_ON_POS); #endif #ifdef CONFIG_SERIAL sys_set_bit(pdctl0, CC2650_PRCM_PDCTL0_SERIAL_ON_POS); #endif /* Setup clocking */ #ifdef CONFIG_GPIO_CC2650 sys_set_bit(gpioclkgr, CC2650_PRCM_GPIOCLKGR_CLK_EN_POS); #endif #ifdef CONFIG_SERIAL sys_set_bit(uartclkgr, CC2650_PRCM_UARTCLKGR_CLK_EN_POS); #endif /* Reload clocking configuration for device */ sys_set_bit(clkloadctl, CC2650_PRCM_CLKLOADCTL_LOAD_POS); /* Wait for power to be completely on, to avoid bus faults * when accessing modules' registers. */ #if defined(CONFIG_GPIO_CC2650) while (!(sys_read32(pdstat0) & BIT(CC2650_PRCM_PDSTAT0_PERIPH_ON_POS))) { continue; } #endif #if defined(CONFIG_SERIAL) while (!(sys_read32(pdstat0) & BIT(CC2650_PRCM_PDSTAT0_SERIAL_ON_POS))) { continue; } #endif #endif }
/** * @brief Halt SPI module operation. * @param dev Pointer to the device structure for the driver instance * @return None. */ static inline void spi_k64_halt(struct device *dev) { struct spi_k64_config *info = dev->config->config_info; /* Ensure module operation is stopped */ sys_set_bit((info->regs + SPI_K64_REG_MCR), SPI_K64_MCR_HALT_BIT); while (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TXRXS) { DBG("SPI Controller dev %p is running. Waiting for Halt.\n", dev); } }
/** * @brief Find the currently executing interrupt vector, if any * * This routine finds the vector of the interrupt that is being processed. * The ISR (In-Service Register) register contain the vectors of the interrupts * in service. And the higher vector is the identification of the interrupt * being currently processed. * * This function must be called with interrupts locked in interrupt context. * * ISR registers' offsets: * -------------------- * | Offset | bits | * -------------------- * | 0100H | 0:31 | * | 0110H | 32:63 | * | 0120H | 64:95 | * | 0130H | 96:127 | * | 0140H | 128:159 | * | 0150H | 160:191 | * | 0160H | 192:223 | * | 0170H | 224:255 | * -------------------- * * @return The vector of the interrupt that is currently being processed, or -1 * if no IRQ is being serviced. */ int __irq_controller_isr_vector_get(void) { int pReg, block; /* Block 0 bits never lit up as these are all exception or reserved * vectors */ for (block = 7; likely(block > 0); block--) { pReg = sys_read32(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_ISR + (block * 0x10)); if (pReg) { return (block * 32) + (find_msb_set(pReg) - 1); } } return -1; }
/** * @brief Suspend SPI host controller operations. * @param dev Pointer to the device structure for the driver instance * @return DEV_OK if successful, another DEV_* code otherwise. */ static int spi_k64_suspend(struct device *dev) { struct spi_k64_config *info = dev->config->config_info; DBG("spi_k64_suspend: %p\n", dev); /* disable module */ sys_set_bit((info->regs + SPI_K64_REG_MCR), SPI_K64_MCR_MDIS_BIT); irq_disable(info->irq); while (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TXRXS) { DBG("SPI Controller dev %p is running. Waiting to stop.\n", dev); } return DEV_OK; }
/** * * @brief modify interrupt line register. * * @param irq INTIN number * @param value value to be written * @param mask of bits to be modified * * @returns N/A */ static void _mvic_rte_update(unsigned int irq, u32_t value, u32_t mask) { int key; u32_t regsel, old_value, updated_value; __ASSERT(!(value & ~MVIC_IOWIN_SUPPORTED_BITS_MASK), "invalid IRQ flags %" PRIx32 " for irq %d", value, irq); regsel = compute_ioregsel(irq); key = irq_lock(); sys_write32(regsel, MVIC_IOREGSEL); old_value = sys_read32(MVIC_IOWIN); updated_value = (old_value & ~mask) | (value & mask); sys_write32(updated_value, MVIC_IOWIN); irq_unlock(key); }
static int _loapic_init(struct device *unused) { ARG_UNUSED(unused); s32_t loApicMaxLvt; /* local APIC Max LVT */ /* enable the Local APIC */ sys_write32(sys_read32(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_SVR) | LOAPIC_ENABLE, CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_SVR); loApicMaxLvt = (*(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_VER) & LOAPIC_MAXLVT_MASK) >> 16; /* reset the DFR, TPR, TIMER_CONFIG, and TIMER_ICR */ *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_DFR) = (int)0xffffffff; *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TPR) = (int)0x0; *(volatile int *) (CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER_CONFIG) = (int)0x0; *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER_ICR) = (int)0x0; /* program Local Vector Table for the Virtual Wire Mode */ /* set LINT0: extInt, high-polarity, edge-trigger, not-masked */ *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_LINT0) = (*(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_LINT0) & ~(LOAPIC_MODE | LOAPIC_LOW | LOAPIC_LEVEL | LOAPIC_LVT_MASKED)) | (LOAPIC_EXT | LOAPIC_HIGH | LOAPIC_EDGE); /* set LINT1: NMI, high-polarity, edge-trigger, not-masked */ *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_LINT1) = (*(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_LINT1) & ~(LOAPIC_MODE | LOAPIC_LOW | LOAPIC_LEVEL | LOAPIC_LVT_MASKED)) | (LOAPIC_NMI | LOAPIC_HIGH | LOAPIC_EDGE); /* lock the Local APIC interrupts */ *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER) = LOAPIC_LVT_MASKED; *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_ERROR) = LOAPIC_LVT_MASKED; if (loApicMaxLvt >= LOAPIC_LVT_P6) *(volatile int *) (CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_PMC) = LOAPIC_LVT_MASKED; if (loApicMaxLvt >= LOAPIC_LVT_PENTIUM4) *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_THERMAL) = LOAPIC_LVT_MASKED; #if CONFIG_LOAPIC_SPURIOUS_VECTOR *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_SVR) = (*(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_SVR) & 0xFFFFFF00) | (LOAPIC_SPURIOUS_VECTOR_ID & 0xFF); #endif /* discard a pending interrupt if any */ #if CONFIG_EOI_FORWARDING_BUG _lakemont_eoi(); #else *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_EOI) = 0; #endif return 0; }
/** * @brief Read and/or write a defined amount of data through an SPI driver * * @param dev Pointer to the device structure for the driver instance * @param tx_buf Memory buffer that data should be transferred from * @param tx_buf_len Size of the memory buffer available for reading from * @param rx_buf Memory buffer that data should be transferred to * @param rx_buf_len Size of the memory buffer available for writing to * * @return DEV_OK if successful, another DEV_* code otherwise. */ static int spi_k64_transceive(struct device *dev, uint8_t *tx_buf, uint32_t tx_buf_len, uint8_t *rx_buf, uint32_t rx_buf_len) { struct spi_k64_config *info = dev->config->config_info; struct spi_k64_data *spi_data = dev->driver_data; uint32_t int_config; /* interrupt configuration */ DBG("spi_k64_transceive: dev %p, Tx buf %p, ", dev, tx_buf); DBG("Tx len %u, Rx buf %p, Rx len %u\n", tx_buf_len, rx_buf, rx_buf_len); /* Check parameters */ if ((tx_buf_len && (tx_buf == NULL)) || (rx_buf_len && (rx_buf == NULL))) { DBG("spi_k64_transceive: ERROR - NULL buffer\n"); return DEV_INVALID_OP; } /* Check Tx FIFO status */ if (tx_buf_len && ((sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TFFF) == 0)) { DBG("spi_k64_transceive: Tx FIFO is full\n"); return DEV_USED; } /* Set buffers info */ spi_data->tx_buf = tx_buf; spi_data->tx_buf_len = tx_buf_len; spi_data->rx_buf = rx_buf; spi_data->rx_buf_len = rx_buf_len; /* enable transfer operations - must be done before enabling interrupts */ spi_k64_start(dev); /* * Enable interrupts: * - Transmit FIFO Fill (Tx FIFO not full); and/or * - Receive FIFO Drain (Rx FIFO not empty); * * Note: DMA requests are not supported. */ int_config = sys_read32(info->regs + SPI_K64_REG_RSER); if (tx_buf_len) { int_config |= SPI_K64_RSER_TFFF_RE; } if (rx_buf_len) { int_config |= SPI_K64_RSER_RFDF_RE; } sys_write32(int_config, (info->regs + SPI_K64_REG_RSER)); /* wait for transfer to complete */ device_sync_call_wait(&spi_data->sync_info); /* check completion status */ if (spi_data->error) { spi_data->error = 0; return DEV_FAIL; } return DEV_OK; }
static uint32_t quark_se_ipm_sts_get(void) { return sys_read32(QUARK_SE_IPM_CHALL_STS) & inbound_channels; }
int bit_is_set(u32_t reg, u8_t bit) { return sys_read32(reg) & BIT(bit); }
/** * @brief SPI module data push (write) operation. * @param dev Pointer to the device structure for the driver instance * @return None. */ static void spi_k64_push_data(struct device *dev) { struct spi_k64_config *info = dev->config->config_info; struct spi_k64_data *spi_data = dev->driver_data; uint32_t data; #ifdef CONFIG_SPI_DEBUG uint32_t cnt = 0; /* # of bytes pushed */ #endif DBG("spi_k64_push_data - "); do { /* initial status already checked by spi_k64_isr() */ if (spi_data->tx_buf && (spi_data->tx_buf_len > 0)) { if (spi_data->frame_sz > CHAR_BIT) { /* get 2nd byte with frame sizes larger than 8 bits */ data = (uint32_t)(*(uint16_t *)(spi_data->tx_buf)); spi_data->tx_buf += 2; spi_data->tx_buf_len -= 2; #ifdef CONFIG_SPI_DEBUG cnt+=2; #endif } else { data = (uint32_t)(*(spi_data->tx_buf)); spi_data->tx_buf++; spi_data->tx_buf_len--; #ifdef CONFIG_SPI_DEBUG cnt++; #endif } /* Write data to the selected slave */ if (spi_data->cont_pcs_sel && (spi_data->tx_buf_len == 0)) { /* clear continuous PCS enabling in the last frame */ sys_write32((data | SPI_K64_PUSHR_PCS_SET(spi_data->pcs)), (info->regs + SPI_K64_REG_PUSHR)); } else { sys_write32((data | SPI_K64_PUSHR_PCS_SET(spi_data->pcs) | SPI_K64_PUSHR_CONT_SET(spi_data->cont_pcs_sel)), (info->regs + SPI_K64_REG_PUSHR)); } /* Clear interrupt */ sys_write32(SPI_K64_SR_TFFF, (info->regs + SPI_K64_REG_SR)); } else { /* Nothing more to push */ break; } } while (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TFFF); DBG("pushed: %d\n", cnt); }
static inline uint32_t eth_read(uint32_t base_addr, uint32_t offset) { return sys_read32(base_addr + offset); }
static inline uint32_t _i2c_qse_ss_memory_read(uint32_t base_addr, uint32_t offset) { return sys_read32(base_addr + offset); }
static u32_t dma_stm32_read(struct dma_stm32_device *ddata, u32_t reg) { return sys_read32(ddata->base + reg); }
static inline void gpio_dw_unmask_int(uint32_t mask_addr) { sys_write32(sys_read32(mask_addr) & INT_ENABLE_ARC, mask_addr); }
static inline void gpio_dw_unmask_int(uint32_t mask_addr) { sys_write32(sys_read32(mask_addr) & INT_UNMASK_IA, mask_addr); }
/** * @brief Complete SPI module data transfer operations. * @param dev Pointer to the device structure for the driver instance * @param error Error condition (0 = no error, otherwise an error occurred) * @return None. */ static void spi_k64_complete(struct device *dev, uint32_t error) { struct spi_k64_data *spi_data = dev->driver_data; struct spi_k64_config *info = dev->config->config_info; uint32_t int_config; /* interrupt configuration */ if (error) { DBG("spi_k64_complete - ERROR condition\n"); goto complete; } /* Check for a completed transfer */ if (spi_data->tx_buf && (spi_data->tx_buf_len == 0) && !spi_data->rx_buf) { /* disable Tx interrupts */ int_config = sys_read32(info->regs + SPI_K64_REG_RSER); int_config &= ~SPI_K64_RSER_TFFF_RE; sys_write32(int_config, (info->regs + SPI_K64_REG_RSER)); } else if (spi_data->rx_buf && (spi_data->rx_buf_len == 0) && !spi_data->tx_buf) { /* disable Rx interrupts */ int_config = sys_read32(info->regs + SPI_K64_REG_RSER); int_config &= ~SPI_K64_RSER_RFDF_RE; sys_write32(int_config, (info->regs + SPI_K64_REG_RSER)); } else if (spi_data->tx_buf && spi_data->tx_buf_len == 0 && spi_data->rx_buf && spi_data->rx_buf_len == 0) { /* disable Tx, Rx interrupts */ int_config = sys_read32(info->regs + SPI_K64_REG_RSER); int_config &= ~(SPI_K64_RSER_TFFF_RE | SPI_K64_RSER_RFDF_RE); sys_write32(int_config, (info->regs + SPI_K64_REG_RSER)); } else { return; } complete: spi_data->tx_buf = spi_data->rx_buf = NULL; spi_data->tx_buf_len = spi_data->rx_buf_len = 0; /* Disable transfer operations */ spi_k64_halt(dev); /* Save status */ spi_data->error = error; /* Signal completion */ device_sync_call_complete(&spi_data->sync_info); }
int spi_k64_init(struct device *dev) { struct spi_k64_config *info = dev->config->config_info; struct spi_k64_data *data = dev->driver_data; uint32_t mcr; dev->driver_api = &k64_spi_api; /* Enable module clocking */ sys_set_bit(info->clk_gate_reg, info->clk_gate_bit); /* * Ensure module operation is stopped and enabled before writing anything * more to the registers. * (Clear MCR[MDIS] and set MCR[HALT].) */ DBG("halt\n"); mcr = SPI_K64_MCR_HALT; sys_write32(mcr, (info->regs + SPI_K64_REG_MCR)); while (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TXRXS) { DBG("SPI Controller dev %p is running. Waiting for Halt.\n", dev); } /* Clear Tx and Rx FIFOs */ mcr |= (SPI_K64_MCR_CLR_RXF | SPI_K64_MCR_CLR_TXF); DBG("fifo clr\n"); sys_write32(mcr, (info->regs + SPI_K64_REG_MCR)); /* Set master mode */ mcr = SPI_K64_MCR_MSTR | SPI_K64_MCR_HALT; DBG("master mode\n"); sys_write32(mcr, (info->regs + SPI_K64_REG_MCR)); /* Disable SPI module interrupt generation */ DBG("irq disable\n"); sys_write32(0, (info->regs + SPI_K64_REG_RSER)); /* Clear status */ DBG("status clr\n"); sys_write32((SPI_K64_SR_RFDF | SPI_K64_SR_RFOF | SPI_K64_SR_TFUF | SPI_K64_SR_EOQF | SPI_K64_SR_TCF), (info->regs + SPI_K64_REG_SR)); /* Set up the synchronous call mechanism */ device_sync_call_init(&data->sync_info); /* Configure and enable SPI module IRQs */ info->config_func(); irq_enable(info->irq); /* * Enable Rx overflow interrupt generation. * Note that Tx underflow is only generated when in slave mode. */ DBG("rxfifo overflow enable\n"); sys_write32(SPI_K64_RSER_RFOF_RE, (info->regs + SPI_K64_REG_RSER)); DBG("K64 SPI Driver initialized on device: %p\n", dev); /* operation remains disabled (MCR[HALT] = 1)*/ return DEV_OK; }