drivers: fpga: add driver for renesas slg471X5
add driver for renesas slg471X5 Signed-off-by: Elias Speinle <e.speinle@vogl-electronic.com>
This commit is contained in:
parent
2ea9483009
commit
c4dba39548
@ -9,3 +9,4 @@ zephyr_library_sources_ifdef(CONFIG_EOS_S3_FPGA fpga_eos_s3.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ICE40_FPGA fpga_ice40.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_MPFS_FPGA fpga_mpfs.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ZYNQMP_FPGA fpga_zynqmp.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SLG471X5_FPGA fpga_slg471x5.c)
|
||||
|
||||
@ -31,5 +31,6 @@ source "drivers/fpga/Kconfig.eos_s3"
|
||||
source "drivers/fpga/Kconfig.ice40"
|
||||
source "drivers/fpga/Kconfig.mpfs"
|
||||
source "drivers/fpga/Kconfig.zynqmp"
|
||||
source "drivers/fpga/Kconfig.slg471x5"
|
||||
|
||||
endif # FPGA
|
||||
|
||||
10
drivers/fpga/Kconfig.slg471x5
Normal file
10
drivers/fpga/Kconfig.slg471x5
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright 2024 Vogl Electronic GmbH
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config SLG471X5_FPGA
|
||||
bool "Renesas SLG47105/SLG47115 GreenPAK Configurable Mixed-Signal IC"
|
||||
default y
|
||||
depends on DT_HAS_RENESAS_SLG47105_ENABLED || DT_HAS_RENESAS_SLG47115_ENABLED
|
||||
select SPI
|
||||
help
|
||||
Enable Renesas SLG47105/SLG47115 driver support.
|
||||
204
drivers/fpga/fpga_slg471x5.c
Normal file
204
drivers/fpga/fpga_slg471x5.c
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Vogl Electronic GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/fpga.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(fpga_slg471x5);
|
||||
|
||||
#define SLG471X5_NREG 256
|
||||
|
||||
#define SLG471X5_I2C_RST_REG 0xF5U
|
||||
#define SLG471X5_I2C_RST_BIT BIT(0)
|
||||
|
||||
#define SLG471X5_ADDR_UNCONFIGURED 0x00U
|
||||
|
||||
/*
|
||||
* mem_region_t - Memory Region
|
||||
*
|
||||
* @addr starting address of memory region
|
||||
* @len size of memory region
|
||||
*/
|
||||
typedef union {
|
||||
uint16_t mem_region;
|
||||
struct {
|
||||
uint8_t addr;
|
||||
uint8_t len;
|
||||
} __packed;
|
||||
} mem_region_t;
|
||||
|
||||
struct fpga_slg471x5_data {
|
||||
bool loaded;
|
||||
struct k_spinlock lock;
|
||||
};
|
||||
|
||||
struct fpga_slg471x5_config {
|
||||
struct i2c_dt_spec bus;
|
||||
mem_region_t *verify_list;
|
||||
int verify_list_len;
|
||||
bool try_unconfigured;
|
||||
};
|
||||
|
||||
static enum FPGA_status fpga_slg471x5_get_status(const struct device *dev)
|
||||
{
|
||||
enum FPGA_status status;
|
||||
k_spinlock_key_t key;
|
||||
struct fpga_slg471x5_data *data = dev->data;
|
||||
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
if (data->loaded) {
|
||||
status = FPGA_STATUS_ACTIVE;
|
||||
} else {
|
||||
status = FPGA_STATUS_INACTIVE;
|
||||
}
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int fpga_slg471x5_verify(const struct device *dev, uint8_t *img, uint32_t img_size)
|
||||
{
|
||||
const struct fpga_slg471x5_config *config = dev->config;
|
||||
uint8_t buf[SLG471X5_NREG] = {0}, addr, len;
|
||||
int i;
|
||||
|
||||
i2c_read_dt(&config->bus, buf, SLG471X5_NREG);
|
||||
|
||||
for (i = 0; i < config->verify_list_len; i++) {
|
||||
addr = config->verify_list[i].addr;
|
||||
len = config->verify_list[i].len;
|
||||
if (memcmp(&img[addr], &buf[addr], len) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fpga_slg471x5_load(const struct device *dev, uint32_t *image_ptr, uint32_t img_size)
|
||||
{
|
||||
const struct fpga_slg471x5_config *config = dev->config;
|
||||
struct fpga_slg471x5_data *data = dev->data;
|
||||
uint8_t buf[SLG471X5_NREG + 1];
|
||||
int ret;
|
||||
|
||||
if (img_size > SLG471X5_NREG) {
|
||||
img_size = SLG471X5_NREG;
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
memcpy(buf + 1, image_ptr, img_size);
|
||||
|
||||
if (config->try_unconfigured) {
|
||||
ret = i2c_write(config->bus.bus, buf, img_size + 1, SLG471X5_ADDR_UNCONFIGURED);
|
||||
if (ret == 0) {
|
||||
ret = fpga_slg471x5_verify(dev, buf + 1, img_size);
|
||||
if (ret == 0) {
|
||||
data->loaded = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = i2c_write_dt(&config->bus, buf, img_size + 1);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Loading bitstream failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fpga_slg471x5_verify(dev, buf + 1, img_size);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Verification failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->loaded = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fpga_slg471x5_reset(const struct device *dev)
|
||||
{
|
||||
const struct fpga_slg471x5_config *config = dev->config;
|
||||
struct fpga_slg471x5_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
ret = i2c_reg_update_byte_dt(&config->bus, SLG471X5_I2C_RST_REG, SLG471X5_I2C_RST_BIT,
|
||||
SLG471X5_I2C_RST_BIT);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->loaded = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fpga_driver_api fpga_slg471x5_api = {
|
||||
.get_status = fpga_slg471x5_get_status,
|
||||
.reset = fpga_slg471x5_reset,
|
||||
.load = fpga_slg471x5_load,
|
||||
};
|
||||
|
||||
static int fpga_slg471x5_init(const struct device *dev)
|
||||
{
|
||||
const struct fpga_slg471x5_config *config = dev->config;
|
||||
|
||||
if (!i2c_is_ready_dt(&config->bus)) {
|
||||
LOG_ERR("I2C bus %s not ready", config->bus.bus->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SLG471X5_INIT(type, inst) \
|
||||
static struct fpga_slg471x5_data fpga_slg##type##_data_##inst; \
|
||||
\
|
||||
static mem_region_t fpga_slg##type##_verify_list[] = FPGA_SLG##type##_VERIFY_LIST; \
|
||||
\
|
||||
static const struct fpga_slg471x5_config fpga_slg##type##_config_##inst = { \
|
||||
.bus = I2C_DT_SPEC_INST_GET(inst), \
|
||||
.verify_list = fpga_slg##type##_verify_list, \
|
||||
.verify_list_len = sizeof(fpga_slg##type##_verify_list) / sizeof(mem_region_t), \
|
||||
.try_unconfigured = DT_INST_NODE_HAS_PROP(inst, try_unconfigured), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, fpga_slg471x5_init, NULL, &fpga_slg##type##_data_##inst, \
|
||||
&fpga_slg##type##_config_##inst, POST_KERNEL, \
|
||||
CONFIG_FPGA_INIT_PRIORITY, &fpga_slg471x5_api)
|
||||
|
||||
#define FPGA_SLG47105_VERIFY_LIST \
|
||||
{ \
|
||||
{.addr = 0x00, .len = 0x47}, \
|
||||
{.addr = 0x4C, .len = 0x01}, \
|
||||
{.addr = 0xFD, .len = 0x01}, \
|
||||
}
|
||||
|
||||
#define SLG47105_INIT(inst) SLG471X5_INIT(47105, inst)
|
||||
#undef DT_DRV_COMPAT
|
||||
#define DT_DRV_COMPAT renesas_slg47105
|
||||
DT_INST_FOREACH_STATUS_OKAY(SLG47105_INIT)
|
||||
|
||||
#define FPGA_SLG47115_VERIFY_LIST \
|
||||
{ \
|
||||
{.addr = 0x00, .len = 0x47}, \
|
||||
{.addr = 0x4C, .len = 0x01}, \
|
||||
{.addr = 0xFD, .len = 0x01}, \
|
||||
}
|
||||
|
||||
#define SLG47115_INIT(inst) SLG471X5_INIT(47115, inst)
|
||||
#undef DT_DRV_COMPAT
|
||||
#define DT_DRV_COMPAT renesas_slg47115
|
||||
DT_INST_FOREACH_STATUS_OKAY(SLG47115_INIT)
|
||||
8
dts/bindings/fpga/renesas,slg47105.yaml
Normal file
8
dts/bindings/fpga/renesas,slg47105.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
# Copyright 2024 Vogl Electronic GmbH
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Renesas SLG47105 GreenPAK Configurable Mixed-Signal IC
|
||||
|
||||
compatible: "renesas,slg47105"
|
||||
|
||||
include: renesas,slg471x5.yaml
|
||||
8
dts/bindings/fpga/renesas,slg47115.yaml
Normal file
8
dts/bindings/fpga/renesas,slg47115.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
# Copyright 2024 Vogl Electronic GmbH
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Renesas SLG47115 GreenPAK Configurable Mixed-Signal IC
|
||||
|
||||
compatible: "renesas,slg47115"
|
||||
|
||||
include: renesas,slg471x5.yaml
|
||||
15
dts/bindings/fpga/renesas,slg471x5.yaml
Normal file
15
dts/bindings/fpga/renesas,slg471x5.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright 2024 Vogl Electronic GmbH
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Renesas SLG47105/SLG47115 GreenPAK Configurable Mixed-Signal IC
|
||||
|
||||
compatible: "renesas,slg471x5"
|
||||
|
||||
include: i2c-device.yaml
|
||||
|
||||
properties:
|
||||
try-unconfigured:
|
||||
type: boolean
|
||||
description: |
|
||||
If selected driver will test transaction on address 0x0 first, before
|
||||
trying address defined in devicetree.
|
||||
Loading…
Reference in New Issue
Block a user