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 #include <zephyr/kernel.h>
9 #include <zephyr/logging/log.h>
10
11 #include "fpga_ice40_common.h"
12
13 LOG_MODULE_REGISTER(fpga_ice40);
14
fpga_ice40_crc_to_str(uint32_t crc,char * s)15 void fpga_ice40_crc_to_str(uint32_t crc, char *s)
16 {
17 char ch;
18 uint8_t i;
19 uint8_t nibble;
20 const char *table = "0123456789abcdef";
21
22 for (i = 0; i < sizeof(crc) * NIBBLES_PER_BYTE; ++i, crc >>= BITS_PER_NIBBLE) {
23 nibble = crc & GENMASK(BITS_PER_NIBBLE, 0);
24 ch = table[nibble];
25 s[sizeof(crc) * NIBBLES_PER_BYTE - i - 1] = ch;
26 }
27
28 s[sizeof(crc) * NIBBLES_PER_BYTE] = '\0';
29 }
30
fpga_ice40_get_status(const struct device * dev)31 enum FPGA_status fpga_ice40_get_status(const struct device *dev)
32 {
33 enum FPGA_status st;
34 k_spinlock_key_t key;
35 struct fpga_ice40_data *data = dev->data;
36
37 key = k_spin_lock(&data->lock);
38
39 if (data->loaded && data->on) {
40 st = FPGA_STATUS_ACTIVE;
41 } else {
42 st = FPGA_STATUS_INACTIVE;
43 }
44
45 k_spin_unlock(&data->lock, key);
46
47 return st;
48 }
49
fpga_ice40_on_off(const struct device * dev,bool on)50 static int fpga_ice40_on_off(const struct device *dev, bool on)
51 {
52 int ret;
53 k_spinlock_key_t key;
54 struct fpga_ice40_data *data = dev->data;
55 const struct fpga_ice40_config *config = dev->config;
56
57 key = k_spin_lock(&data->lock);
58
59 ret = gpio_pin_configure_dt(&config->creset, on ? GPIO_OUTPUT_HIGH : GPIO_OUTPUT_LOW);
60 if (ret < 0) {
61 goto unlock;
62 }
63
64 data->on = on;
65 ret = 0;
66
67 unlock:
68 k_spin_unlock(&data->lock, key);
69
70 return ret;
71 }
72
fpga_ice40_on(const struct device * dev)73 int fpga_ice40_on(const struct device *dev)
74 {
75 return fpga_ice40_on_off(dev, true);
76 }
77
fpga_ice40_off(const struct device * dev)78 int fpga_ice40_off(const struct device *dev)
79 {
80 return fpga_ice40_on_off(dev, false);
81 }
82
fpga_ice40_reset(const struct device * dev)83 int fpga_ice40_reset(const struct device *dev)
84 {
85 return fpga_ice40_off(dev) || fpga_ice40_on(dev);
86 }
87
fpga_ice40_get_info(const struct device * dev)88 const char *fpga_ice40_get_info(const struct device *dev)
89 {
90 struct fpga_ice40_data *data = dev->data;
91
92 return data->info;
93 }
94
fpga_ice40_init(const struct device * dev)95 int fpga_ice40_init(const struct device *dev)
96 {
97 int ret;
98 const struct fpga_ice40_config *config = dev->config;
99
100 if (!device_is_ready(config->creset.port)) {
101 LOG_ERR("%s: GPIO for creset is not ready", dev->name);
102 return -ENODEV;
103 }
104
105 if (!device_is_ready(config->cdone.port)) {
106 LOG_ERR("%s: GPIO for cdone is not ready", dev->name);
107 return -ENODEV;
108 }
109
110 ret = gpio_pin_configure_dt(&config->creset, GPIO_OUTPUT_HIGH);
111 if (ret < 0) {
112 LOG_ERR("failed to configure CRESET: %d", ret);
113 return ret;
114 }
115
116 ret = gpio_pin_configure_dt(&config->cdone, GPIO_INPUT);
117 if (ret < 0) {
118 LOG_ERR("Failed to initialize CDONE: %d", ret);
119 return ret;
120 }
121
122 return 0;
123 }
124