1 /*
2  * Copyright (c) 2022 Meta
3  * Copyright (c) 2024 SILA Embedded Solutions GmbH
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef ZEPHYR_SUBSYS_FPGA_FPGA_ICE40_COMMON_H_
9 #define ZEPHYR_SUBSYS_FPGA_FPGA_ICE40_COMMON_H_
10 
11 #include <stdbool.h>
12 #include <stdint.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/drivers/fpga.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/drivers/spi.h>
17 
18 /*
19  * Values in Hz, intentionally to be comparable with the spi-max-frequency
20  * property from DT bindings in spi-device.yaml.
21  */
22 #define FPGA_ICE40_SPI_HZ_MIN 1000000
23 #define FPGA_ICE40_SPI_HZ_MAX 25000000
24 
25 #define FPGA_ICE40_CRESET_DELAY_US_MIN 1 /* 200ns absolute minimum */
26 #define FPGA_ICE40_CONFIG_DELAY_US_MIN 1200
27 #define FPGA_ICE40_LEADING_CLOCKS_MIN  8
28 #define FPGA_ICE40_TRAILING_CLOCKS_MIN 49
29 
30 #define FPGA_ICE40_CONFIG_DEFINE(inst, derived_config_)                                            \
31 	BUILD_ASSERT(DT_INST_PROP(inst, spi_max_frequency) >= FPGA_ICE40_SPI_HZ_MIN);              \
32 	BUILD_ASSERT(DT_INST_PROP(inst, spi_max_frequency) <= FPGA_ICE40_SPI_HZ_MAX);              \
33 	BUILD_ASSERT(DT_INST_PROP(inst, config_delay_us) >= FPGA_ICE40_CONFIG_DELAY_US_MIN);       \
34 	BUILD_ASSERT(DT_INST_PROP(inst, config_delay_us) <= UINT16_MAX);                           \
35 	BUILD_ASSERT(DT_INST_PROP(inst, creset_delay_us) >= FPGA_ICE40_CRESET_DELAY_US_MIN);       \
36 	BUILD_ASSERT(DT_INST_PROP(inst, creset_delay_us) <= UINT16_MAX);                           \
37 	BUILD_ASSERT(DT_INST_PROP(inst, leading_clocks) >= FPGA_ICE40_LEADING_CLOCKS_MIN);         \
38 	BUILD_ASSERT(DT_INST_PROP(inst, leading_clocks) <= UINT8_MAX);                             \
39 	BUILD_ASSERT(DT_INST_PROP(inst, trailing_clocks) >= FPGA_ICE40_TRAILING_CLOCKS_MIN);       \
40 	BUILD_ASSERT(DT_INST_PROP(inst, trailing_clocks) <= UINT8_MAX);                            \
41 	                                                                                           \
42 	static const struct fpga_ice40_config fpga_ice40_config_##inst = {                         \
43 		.bus = SPI_DT_SPEC_INST_GET(inst,                                                  \
44 					    SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA |   \
45 						    SPI_WORD_SET(8) | SPI_TRANSFER_MSB,            \
46 					    0),                                                    \
47 		.creset = GPIO_DT_SPEC_INST_GET(inst, creset_gpios),                               \
48 		.cdone = GPIO_DT_SPEC_INST_GET(inst, cdone_gpios),                                 \
49 		.config_delay_us = DT_INST_PROP(inst, config_delay_us),                            \
50 		.creset_delay_us = DT_INST_PROP(inst, creset_delay_us),                            \
51 		.leading_clocks = DT_INST_PROP(inst, leading_clocks),                              \
52 		.trailing_clocks = DT_INST_PROP(inst, trailing_clocks),                            \
53 		.derived_config = derived_config_,                                                 \
54 	}
55 
56 struct fpga_ice40_data {
57 	uint32_t crc;
58 	/* simply use crc32 as info */
59 	char info[2 * sizeof(uint32_t) + 1];
60 	bool on;
61 	bool loaded;
62 	struct k_spinlock lock;
63 };
64 
65 struct fpga_ice40_config {
66 	struct spi_dt_spec bus;
67 	struct gpio_dt_spec cdone;
68 	struct gpio_dt_spec creset;
69 	uint16_t creset_delay_us;
70 	uint16_t config_delay_us;
71 	uint8_t leading_clocks;
72 	uint8_t trailing_clocks;
73 	const void *derived_config;
74 };
75 
76 void fpga_ice40_crc_to_str(uint32_t crc, char *s);
77 enum FPGA_status fpga_ice40_get_status(const struct device *dev);
78 int fpga_ice40_on(const struct device *dev);
79 int fpga_ice40_off(const struct device *dev);
80 int fpga_ice40_reset(const struct device *dev);
81 const char *fpga_ice40_get_info(const struct device *dev);
82 int fpga_ice40_init(const struct device *dev);
83 
84 #endif /* ZEPHYR_SUBSYS_FPGA_FPGA_ICE40_COMMON_H_ */
85