static int spi_dw_configure(struct device *dev, struct spi_config *config) { const struct spi_dw_config *info = dev->config->config_info; struct spi_dw_data *spi = dev->driver_data; u32_t flags = config->config; u32_t ctrlr0 = 0; u32_t mode; SYS_LOG_DBG("%p (0x%x), %p", dev, info->regs, config); /* Check status */ if (!_spi_dw_is_controller_ready(dev)) { SYS_LOG_DBG("Controller is busy"); return -EBUSY; } /* Word size */ ctrlr0 |= DW_SPI_CTRLR0_DFS(SPI_WORD_SIZE_GET(flags)); /* Determine how many bytes are required per-frame */ spi->dfs = SPI_WS_TO_DFS(SPI_WORD_SIZE_GET(flags)); /* SPI mode */ mode = SPI_MODE(flags); if (mode & SPI_MODE_CPOL) { ctrlr0 |= DW_SPI_CTRLR0_SCPOL; } if (mode & SPI_MODE_CPHA) { ctrlr0 |= DW_SPI_CTRLR0_SCPH; } if (mode & SPI_MODE_LOOP) { ctrlr0 |= DW_SPI_CTRLR0_SRL; } /* Installing the configuration */ write_ctrlr0(ctrlr0, info->regs); /* * Configure the rate. Use this small hack to allow the user to call * spi_configure() with both a divider (as the driver was initially * written) and a frequency (as the SPI API suggests to). The clock * divider is a 16bit value, hence we can fairly, and safely, assume * that everything above this value is a frequency. The trade-off is * that if one wants to use a bus frequency of 64kHz (or less), it has * the use a divider... */ if (config->max_sys_freq > 0xffff) { write_baudr(SPI_DW_CLK_DIVIDER(config->max_sys_freq), info->regs); } else { write_baudr(config->max_sys_freq, info->regs); } return 0; }
static int spi_dw_configure(struct device *dev, struct spi_config *config) { struct spi_dw_config *info = dev->config->config_info; struct spi_dw_data *spi = dev->driver_data; uint32_t flags = config->config; uint32_t ctrlr0 = 0; uint32_t mode; DBG("%s: %p (0x%x), %p\n", __func__, dev, info->regs, config); /* Check status */ if (!_spi_dw_is_controller_ready(dev)) { DBG("%s: Controller is busy\n", __func__); return DEV_USED; } /* Word size */ ctrlr0 |= DW_SPI_CTRLR0_DFS(SPI_WORD_SIZE_GET(flags)); /* Determine how many bytes are required per-frame */ spi->dfs = SPI_DFS_TO_BYTES(SPI_WORD_SIZE_GET(flags)); /* SPI mode */ mode = SPI_MODE(flags); if (mode & SPI_MODE_CPOL) { ctrlr0 |= DW_SPI_CTRLR0_SCPOL; } if (mode & SPI_MODE_CPHA) { ctrlr0 |= DW_SPI_CTRLR0_SCPH; } if (mode & SPI_MODE_LOOP) { ctrlr0 |= DW_SPI_CTRLR0_SRL; } /* Installing the configuration */ write_ctrlr0(ctrlr0, info->regs); /* Configuring the rate */ write_baudr(config->max_sys_freq, info->regs); return DEV_OK; }
static int spi_qmsi_configure(struct device *dev, struct spi_config *config) { struct spi_qmsi_runtime *context = dev->driver_data; qm_spi_config_t *cfg = &context->cfg; cfg->frame_size = SPI_WORD_SIZE_GET(config->config) - 1; cfg->bus_mode = config_to_bmode(SPI_MODE(config->config)); /* As loopback is implemented inside the controller, * the bus mode doesn't matter. */ context->loopback = SPI_MODE(config->config) & SPI_MODE_LOOP; cfg->clk_divider = config->max_sys_freq; /* Will set the configuration before the transfer starts */ return 0; }
static int configure(struct device *dev, const struct spi_config *spi_cfg) { struct spi_context *ctx = &get_dev_data(dev)->ctx; if (spi_context_configured(ctx, spi_cfg)) { /* Already configured. No need to do it again. */ return 0; } if (SPI_OP_MODE_GET(spi_cfg->operation) == SPI_OP_MODE_MASTER) { LOG_ERR("Master mode is not supported on %s", dev->config->name); return -EINVAL; } if (spi_cfg->operation & SPI_MODE_LOOP) { LOG_ERR("Loopback mode is not supported"); return -EINVAL; } if ((spi_cfg->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) { LOG_ERR("Only single line mode is supported"); return -EINVAL; } if (SPI_WORD_SIZE_GET(spi_cfg->operation) != 8) { LOG_ERR("Word sizes other than 8 bits" " are not supported"); return -EINVAL; } if (spi_cfg->cs) { LOG_ERR("CS control via GPIO is not supported"); return -EINVAL; } ctx->config = spi_cfg; nrf_spis_configure(get_dev_config(dev)->spis.p_reg, get_nrf_spis_mode(spi_cfg->operation), get_nrf_spis_bit_order(spi_cfg->operation)); return 0; }
static int spi_stm32_configure(struct spi_config *config) { const struct spi_stm32_config *cfg = CONFIG_CFG(config); struct spi_stm32_data *data = CONFIG_DATA(config); const u32_t scaler[] = { LL_SPI_BAUDRATEPRESCALER_DIV2, LL_SPI_BAUDRATEPRESCALER_DIV4, LL_SPI_BAUDRATEPRESCALER_DIV8, LL_SPI_BAUDRATEPRESCALER_DIV16, LL_SPI_BAUDRATEPRESCALER_DIV32, LL_SPI_BAUDRATEPRESCALER_DIV64, LL_SPI_BAUDRATEPRESCALER_DIV128, LL_SPI_BAUDRATEPRESCALER_DIV256 }; SPI_TypeDef *spi = cfg->spi; u32_t clock; int br; if (spi_context_configured(&data->ctx, config)) { /* Nothing to do */ return 0; } if (SPI_WORD_SIZE_GET(config->operation) != 8) { return -ENOTSUP; } clock_control_get_rate(device_get_binding(STM32_CLOCK_CONTROL_NAME), (clock_control_subsys_t) &cfg->pclken, &clock); for (br = 1 ; br <= ARRAY_SIZE(scaler) ; ++br) { u32_t clk = clock >> br; if (clk < config->frequency) { break; } } if (br > ARRAY_SIZE(scaler)) { SYS_LOG_ERR("Unsupported frequency %uHz, max %uHz, min %uHz", config->frequency, clock >> 1, clock >> ARRAY_SIZE(scaler)); return -EINVAL; }
static int spi_dw_configure(const struct spi_dw_config *info, struct spi_dw_data *spi, const struct spi_config *config) { u32_t ctrlr0 = 0U; LOG_DBG("%p (prev %p)", config, spi->ctx.config); if (spi_context_configured(&spi->ctx, config)) { /* Nothing to do */ return 0; } /* Verify if requested op mode is relevant to this controller */ if (config->operation & SPI_OP_MODE_SLAVE) { if (!(info->op_modes & SPI_CTX_RUNTIME_OP_MODE_SLAVE)) { LOG_ERR("Slave mode not supported"); return -ENOTSUP; } } else { if (!(info->op_modes & SPI_CTX_RUNTIME_OP_MODE_MASTER)) { LOG_ERR("Master mode not supported"); return -ENOTSUP; } } if (config->operation & (SPI_TRANSFER_LSB | SPI_LINES_DUAL | SPI_LINES_QUAD)) { LOG_ERR("Unsupported configuration"); return -EINVAL; } /* Word size */ ctrlr0 |= DW_SPI_CTRLR0_DFS(SPI_WORD_SIZE_GET(config->operation)); /* Determine how many bytes are required per-frame */ spi->dfs = SPI_WS_TO_DFS(SPI_WORD_SIZE_GET(config->operation)); /* SPI mode */ if (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) { ctrlr0 |= DW_SPI_CTRLR0_SCPOL; } if (SPI_MODE_GET(config->operation) & SPI_MODE_CPHA) { ctrlr0 |= DW_SPI_CTRLR0_SCPH; } if (SPI_MODE_GET(config->operation) & SPI_MODE_LOOP) { ctrlr0 |= DW_SPI_CTRLR0_SRL; } /* Installing the configuration */ write_ctrlr0(ctrlr0, info->regs); /* At this point, it's mandatory to set this on the context! */ spi->ctx.config = config; if (!spi_dw_is_slave(spi)) { /* Baud rate and Slave select, for master only */ write_baudr(SPI_DW_CLK_DIVIDER(config->frequency), info->regs); write_ser(1 << config->slave, info->regs); } spi_context_cs_configure(&spi->ctx); if (spi_dw_is_slave(spi)) { LOG_DBG("Installed slave config %p:" " ws/dfs %u/%u, mode %u/%u/%u", config, SPI_WORD_SIZE_GET(config->operation), spi->dfs, (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) ? 1 : 0, (SPI_MODE_GET(config->operation) & SPI_MODE_CPHA) ? 1 : 0, (SPI_MODE_GET(config->operation) & SPI_MODE_LOOP) ? 1 : 0); } else { LOG_DBG("Installed master config %p: freq %uHz (div = %u)," " ws/dfs %u/%u, mode %u/%u/%u, slave %u", config, config->frequency, SPI_DW_CLK_DIVIDER(config->frequency), SPI_WORD_SIZE_GET(config->operation), spi->dfs, (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) ? 1 : 0, (SPI_MODE_GET(config->operation) & SPI_MODE_CPHA) ? 1 : 0, (SPI_MODE_GET(config->operation) & SPI_MODE_LOOP) ? 1 : 0, config->slave); } return 0; }
/** * @brief Configure the SPI host controller for operating against slaves * @param dev Pointer to the device structure for the driver instance * @param config Pointer to the application provided configuration * * @return DEV_OK if successful, another DEV_* code otherwise. */ static int spi_k64_configure(struct device *dev, struct spi_config *config) { struct spi_k64_config *info = dev->config->config_info; struct spi_k64_data *spi_data = dev->driver_data; uint32_t flags = config->config; uint32_t mcr; /* mode configuration attributes, for MCR */ uint32_t ctar = 0; /* clocking and timing attributes, for CTAR */ uint32_t frame_sz; /* frame size, in bits */ DBG("spi_k64_configure: dev %p (regs @ 0x%x), ", dev, info->regs); DBG("config 0x%x, freq 0x%x", config->config, config->max_sys_freq); /* Disable transfer operations during configuration */ spi_k64_halt(dev); /* * Set the common configuration: * Master mode, normal SPI transfers, PCS strobe disabled, * Rx overflow data ignored, PCSx inactive low signal, Doze disabled, * Rx/Tx FIFOs enabled. * * Also, keep transfers disabled. */ mcr = SPI_K64_MCR_MSTR | SPI_K64_MCR_HALT; /* Set PCSx signal polarities and continuous SCK, as requested */ mcr |= (SPI_K64_MCR_PCSIS_SET(SPI_PCS_POL_GET(flags)) | SPI_K64_MCR_CONT_SCKE_SET(SPI_CONT_SCK_GET(flags))); sys_write32(mcr, (info->regs + SPI_K64_REG_MCR)); /* Set clocking and timing parameters */ /* SCK polarity and phase, and bit order of data */ if (flags & SPI_MODE_CPOL) { ctar |= SPI_K64_CTAR_CPOL; } if (flags & SPI_MODE_CPHA) { ctar |= SPI_K64_CTAR_CPHA; } if (flags & SPI_TRANSFER_MASK) { ctar |= SPI_K64_CTAR_LSBFE; } /* * Frame size is limited to 16 bits (vs. 8 bit value in struct spi_config), * programmed as: (frame_size - 1) */ if ((frame_sz = SPI_WORD_SIZE_GET(flags)) > SPI_K64_WORD_SIZE_MAX) { return DEV_INVALID_OP; } spi_data->frame_sz = frame_sz; ctar |= (SPI_K64_CTAR_FRMSZ_SET(frame_sz - 1)); /* Set baud rate and signal timing parameters (delays) */ if (spi_k64_set_baud_rate(config->max_sys_freq, &ctar) == 0) { return DEV_INVALID_OP; } /* * Set signal timing parameters (delays): * - PCS to SCK delay is set to the minimum, CTAR[PCSSCK] = CTAR[CSSCK] = 0; * - After SCK delay is set to at least half of the baud rate period, * (using the combination of CTAR[PASC] and CTAR[ASC]); and * - Delay after transfer is set to the minimum, CTAR[PDT] = CTAR[DT] = 0. */ if (spi_k64_set_delay(DELAY_AFTER_SCK, (NSEC_PER_SEC / 2) / config->max_sys_freq, &ctar) == 0) { return DEV_INVALID_OP; } DBG("spi_k64_configure: MCR: 0x%x CTAR0: 0x%x\n", mcr, ctar); sys_write32(ctar, (info->regs + SPI_K64_REG_CTAR0)); /* Initialize Tx/Rx parameters */ spi_data->tx_buf = spi_data->rx_buf = NULL; spi_data->tx_buf_len = spi_data->rx_buf_len = 0; /* Store continuous slave/PCS signal selection mode */ spi_data->cont_pcs_sel = SPI_CONT_PCS_GET(flags); return DEV_OK; }