zephyr/drivers/fpga/fpga_ice40_common.h
Benedikt Schmidt 760210f39d drivers: fpga: separate drivers of iCE40 for SPI and GPIO bitbang
Separate the current driver for the FPGA iCE40 into two different ones.
One implements only the SPI load mode, the other one only the GPIO
bitbang mode.

Signed-off-by: Benedikt Schmidt <benedikt.schmidt@embedded-solutions.at>
2024-11-28 15:39:33 +00:00

84 lines
3.7 KiB
C

/*
* Copyright (c) 2022 Meta
* Copyright (c) 2024 SILA Embedded Solutions GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_SUBSYS_FPGA_FPGA_ICE40_COMMON_H_
#define ZEPHYR_SUBSYS_FPGA_FPGA_ICE40_COMMON_H_
#include <stdbool.h>
#include <stdint.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/fpga.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/spi.h>
/*
* Values in Hz, intentionally to be comparable with the spi-max-frequency
* property from DT bindings in spi-device.yaml.
*/
#define FPGA_ICE40_SPI_HZ_MIN 1000000
#define FPGA_ICE40_SPI_HZ_MAX 25000000
#define FPGA_ICE40_CRESET_DELAY_US_MIN 1 /* 200ns absolute minimum */
#define FPGA_ICE40_CONFIG_DELAY_US_MIN 1200
#define FPGA_ICE40_LEADING_CLOCKS_MIN 8
#define FPGA_ICE40_TRAILING_CLOCKS_MIN 49
#define FPGA_ICE40_CONFIG_DEFINE(inst, derived_config_) \
BUILD_ASSERT(DT_INST_PROP(inst, spi_max_frequency) >= FPGA_ICE40_SPI_HZ_MIN); \
BUILD_ASSERT(DT_INST_PROP(inst, spi_max_frequency) <= FPGA_ICE40_SPI_HZ_MAX); \
BUILD_ASSERT(DT_INST_PROP(inst, config_delay_us) >= FPGA_ICE40_CONFIG_DELAY_US_MIN); \
BUILD_ASSERT(DT_INST_PROP(inst, config_delay_us) <= UINT16_MAX); \
BUILD_ASSERT(DT_INST_PROP(inst, creset_delay_us) >= FPGA_ICE40_CRESET_DELAY_US_MIN); \
BUILD_ASSERT(DT_INST_PROP(inst, creset_delay_us) <= UINT16_MAX); \
BUILD_ASSERT(DT_INST_PROP(inst, leading_clocks) >= FPGA_ICE40_LEADING_CLOCKS_MIN); \
BUILD_ASSERT(DT_INST_PROP(inst, leading_clocks) <= UINT8_MAX); \
BUILD_ASSERT(DT_INST_PROP(inst, trailing_clocks) >= FPGA_ICE40_TRAILING_CLOCKS_MIN); \
BUILD_ASSERT(DT_INST_PROP(inst, trailing_clocks) <= UINT8_MAX); \
\
static const struct fpga_ice40_config fpga_ice40_config_##inst = { \
.bus = SPI_DT_SPEC_INST_GET(inst, \
SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | \
SPI_WORD_SET(8) | SPI_TRANSFER_MSB, \
0), \
.creset = GPIO_DT_SPEC_INST_GET(inst, creset_gpios), \
.cdone = GPIO_DT_SPEC_INST_GET(inst, cdone_gpios), \
.config_delay_us = DT_INST_PROP(inst, config_delay_us), \
.creset_delay_us = DT_INST_PROP(inst, creset_delay_us), \
.leading_clocks = DT_INST_PROP(inst, leading_clocks), \
.trailing_clocks = DT_INST_PROP(inst, trailing_clocks), \
.derived_config = derived_config_, \
}
struct fpga_ice40_data {
uint32_t crc;
/* simply use crc32 as info */
char info[2 * sizeof(uint32_t) + 1];
bool on;
bool loaded;
struct k_spinlock lock;
};
struct fpga_ice40_config {
struct spi_dt_spec bus;
struct gpio_dt_spec cdone;
struct gpio_dt_spec creset;
uint16_t creset_delay_us;
uint16_t config_delay_us;
uint8_t leading_clocks;
uint8_t trailing_clocks;
const void *derived_config;
};
void fpga_ice40_crc_to_str(uint32_t crc, char *s);
enum FPGA_status fpga_ice40_get_status(const struct device *dev);
int fpga_ice40_on(const struct device *dev);
int fpga_ice40_off(const struct device *dev);
int fpga_ice40_reset(const struct device *dev);
const char *fpga_ice40_get_info(const struct device *dev);
int fpga_ice40_init(const struct device *dev);
#endif /* ZEPHYR_SUBSYS_FPGA_FPGA_ICE40_COMMON_H_ */