blob: 588c1cb7c6297d6f19b7230c3b379f1bbc6bc1a0 [file] [log] [blame]
/*
* 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);
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;
}