You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
2.5 KiB
123 lines
2.5 KiB
/* |
|
* Copyright (c) 2022 Meta |
|
* Copyright (c) 2024 SILA Embedded Solutions GmbH |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#include <zephyr/kernel.h> |
|
#include <zephyr/logging/log.h> |
|
|
|
#include "fpga_ice40_common.h" |
|
|
|
LOG_MODULE_REGISTER(fpga_ice40, CONFIG_FPGA_LOG_LEVEL); |
|
|
|
void fpga_ice40_crc_to_str(uint32_t crc, char *s) |
|
{ |
|
char ch; |
|
uint8_t i; |
|
uint8_t nibble; |
|
const char *table = "0123456789abcdef"; |
|
|
|
for (i = 0; i < sizeof(crc) * NIBBLES_PER_BYTE; ++i, crc >>= BITS_PER_NIBBLE) { |
|
nibble = crc & GENMASK(BITS_PER_NIBBLE, 0); |
|
ch = table[nibble]; |
|
s[sizeof(crc) * NIBBLES_PER_BYTE - i - 1] = ch; |
|
} |
|
|
|
s[sizeof(crc) * NIBBLES_PER_BYTE] = '\0'; |
|
} |
|
|
|
enum FPGA_status fpga_ice40_get_status(const struct device *dev) |
|
{ |
|
enum FPGA_status st; |
|
k_spinlock_key_t key; |
|
struct fpga_ice40_data *data = dev->data; |
|
|
|
key = k_spin_lock(&data->lock); |
|
|
|
if (data->loaded && data->on) { |
|
st = FPGA_STATUS_ACTIVE; |
|
} else { |
|
st = FPGA_STATUS_INACTIVE; |
|
} |
|
|
|
k_spin_unlock(&data->lock, key); |
|
|
|
return st; |
|
} |
|
|
|
static int fpga_ice40_on_off(const struct device *dev, bool on) |
|
{ |
|
int ret; |
|
k_spinlock_key_t key; |
|
struct fpga_ice40_data *data = dev->data; |
|
const struct fpga_ice40_config *config = dev->config; |
|
|
|
key = k_spin_lock(&data->lock); |
|
|
|
ret = gpio_pin_configure_dt(&config->creset, on ? GPIO_OUTPUT_HIGH : GPIO_OUTPUT_LOW); |
|
if (ret < 0) { |
|
goto unlock; |
|
} |
|
|
|
data->on = on; |
|
ret = 0; |
|
|
|
unlock: |
|
k_spin_unlock(&data->lock, key); |
|
|
|
return ret; |
|
} |
|
|
|
int fpga_ice40_on(const struct device *dev) |
|
{ |
|
return fpga_ice40_on_off(dev, true); |
|
} |
|
|
|
int fpga_ice40_off(const struct device *dev) |
|
{ |
|
return fpga_ice40_on_off(dev, false); |
|
} |
|
|
|
int fpga_ice40_reset(const struct device *dev) |
|
{ |
|
return fpga_ice40_off(dev) || fpga_ice40_on(dev); |
|
} |
|
|
|
const char *fpga_ice40_get_info(const struct device *dev) |
|
{ |
|
struct fpga_ice40_data *data = dev->data; |
|
|
|
return data->info; |
|
} |
|
|
|
int fpga_ice40_init(const struct device *dev) |
|
{ |
|
int ret; |
|
const struct fpga_ice40_config *config = dev->config; |
|
|
|
if (!device_is_ready(config->creset.port)) { |
|
LOG_ERR("%s: GPIO for creset is not ready", dev->name); |
|
return -ENODEV; |
|
} |
|
|
|
if (!device_is_ready(config->cdone.port)) { |
|
LOG_ERR("%s: GPIO for cdone is not ready", dev->name); |
|
return -ENODEV; |
|
} |
|
|
|
ret = gpio_pin_configure_dt(&config->creset, GPIO_OUTPUT_HIGH); |
|
if (ret < 0) { |
|
LOG_ERR("failed to configure CRESET: %d", ret); |
|
return ret; |
|
} |
|
|
|
ret = gpio_pin_configure_dt(&config->cdone, GPIO_INPUT); |
|
if (ret < 0) { |
|
LOG_ERR("Failed to initialize CDONE: %d", ret); |
|
return ret; |
|
} |
|
|
|
return 0; |
|
}
|
|
|