Browse Source
This adds driver for EOS_S3 SoC FPGA. Signed-off-by: Mateusz Sierszulski <msierszulski@internships.antmicro.com> Signed-off-by: Tomasz Gorochowik <tgorochowik@antmicro.com>pull/38300/head
13 changed files with 5752 additions and 0 deletions
@ -1,3 +1,5 @@ |
|||||||
# SPDX-License-Identifier: Apache-2.0 |
# SPDX-License-Identifier: Apache-2.0 |
||||||
|
|
||||||
zephyr_library() |
zephyr_library() |
||||||
|
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_EOS_S3_FPGA fpga_eos_s3.c) |
||||||
|
@ -0,0 +1,9 @@ |
|||||||
|
# FPGA EOS S3 driver configuration options |
||||||
|
|
||||||
|
# Copyright (c) 2021 Antmicro <www.antmicro.com> |
||||||
|
# SPDX-License-Identifier: Apache-2.0 |
||||||
|
|
||||||
|
config EOS_S3_FPGA |
||||||
|
bool "EOS S3 fpga driver" |
||||||
|
help |
||||||
|
Enable EOS S3 FPGA driver. |
@ -0,0 +1,146 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Antmicro <www.antmicro.com> |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <errno.h> |
||||||
|
#include <string.h> |
||||||
|
#include <device.h> |
||||||
|
#include <drivers/fpga.h> |
||||||
|
#include "fpga_eos_s3.h" |
||||||
|
|
||||||
|
void eos_s3_fpga_enable_clk(void) |
||||||
|
{ |
||||||
|
CRU->C16_CLK_GATE = C16_CLK_GATE_PATH_0_ON; |
||||||
|
CRU->C21_CLK_GATE = C21_CLK_GATE_PATH_0_ON; |
||||||
|
CRU->C09_CLK_GATE = C09_CLK_GATE_PATH_1_ON | C09_CLK_GATE_PATH_2_ON; |
||||||
|
CRU->C02_CLK_GATE = C02_CLK_GATE_PATH_1_ON; |
||||||
|
} |
||||||
|
|
||||||
|
void eos_s3_fpga_disable_clk(void) |
||||||
|
{ |
||||||
|
CRU->C16_CLK_GATE = C16_CLK_GATE_PATH_0_OFF; |
||||||
|
CRU->C21_CLK_GATE = C21_CLK_GATE_PATH_0_OFF; |
||||||
|
CRU->C09_CLK_GATE = C09_CLK_GATE_PATH_1_OFF | C09_CLK_GATE_PATH_2_OFF; |
||||||
|
CRU->C02_CLK_GATE = C02_CLK_GATE_PATH_1_OFF; |
||||||
|
} |
||||||
|
|
||||||
|
struct quickfeather_fpga_data { |
||||||
|
char *FPGA_info; |
||||||
|
}; |
||||||
|
|
||||||
|
static enum FPGA_status eos_s3_fpga_get_status(const struct device *dev) |
||||||
|
{ |
||||||
|
ARG_UNUSED(dev); |
||||||
|
|
||||||
|
if (PMU->FB_STATUS == FPGA_STATUS_ACTIVE) { |
||||||
|
return FPGA_STATUS_ACTIVE; |
||||||
|
} else |
||||||
|
return FPGA_STATUS_INACTIVE; |
||||||
|
} |
||||||
|
|
||||||
|
static const char *eos_s3_fpga_get_info(const struct device *dev) |
||||||
|
{ |
||||||
|
struct quickfeather_fpga_data *data = dev->data; |
||||||
|
|
||||||
|
return data->FPGA_info; |
||||||
|
} |
||||||
|
|
||||||
|
static int eos_s3_fpga_on(const struct device *dev) |
||||||
|
{ |
||||||
|
if (eos_s3_fpga_get_status(dev) == FPGA_STATUS_ACTIVE) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/* wake up the FPGA power domain */ |
||||||
|
PMU->FFE_FB_PF_SW_WU = PMU_FFE_FB_PF_SW_WU_FB_WU; |
||||||
|
while (PMU->FFE_FB_PF_SW_WU == PMU_FFE_FB_PF_SW_WU_FB_WU) { |
||||||
|
/* The register will clear itself if the FPGA starts */ |
||||||
|
}; |
||||||
|
|
||||||
|
eos_s3_fpga_enable_clk(); |
||||||
|
|
||||||
|
/* enable FPGA programming */ |
||||||
|
PMU->GEN_PURPOSE_0 = FB_CFG_ENABLE; |
||||||
|
PIF->CFG_CTL = CFG_CTL_LOAD_ENABLE; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int eos_s3_fpga_off(const struct device *dev) |
||||||
|
{ |
||||||
|
if (eos_s3_fpga_get_status(dev) == FPGA_STATUS_INACTIVE) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
PMU->FB_PWR_MODE_CFG = PMU_FB_PWR_MODE_CFG_FB_SD; |
||||||
|
PMU->FFE_FB_PF_SW_PD = PMU_FFE_FB_PF_SW_PD_FB_PD; |
||||||
|
|
||||||
|
eos_s3_fpga_disable_clk(); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int eos_s3_fpga_reset(const struct device *dev) |
||||||
|
{ |
||||||
|
if (eos_s3_fpga_get_status(dev) == FPGA_STATUS_ACTIVE) { |
||||||
|
eos_s3_fpga_off(dev); |
||||||
|
} |
||||||
|
|
||||||
|
eos_s3_fpga_on(dev); |
||||||
|
|
||||||
|
if (eos_s3_fpga_get_status(dev) == FPGA_STATUS_INACTIVE) { |
||||||
|
return -EAGAIN; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int eos_s3_fpga_load(const struct device *dev, uint32_t *image_ptr, uint32_t img_size) |
||||||
|
{ |
||||||
|
if (eos_s3_fpga_get_status(dev) == FPGA_STATUS_INACTIVE) { |
||||||
|
return -EINVAL; |
||||||
|
} |
||||||
|
|
||||||
|
volatile uint32_t *bitstream = (volatile uint32_t *)image_ptr; |
||||||
|
|
||||||
|
for (uint32_t chunk_cnt = 0; chunk_cnt < (img_size / 4); chunk_cnt++) { |
||||||
|
PIF->CFG_DATA = *bitstream; |
||||||
|
bitstream++; |
||||||
|
} |
||||||
|
|
||||||
|
/* disable FPGA programming */ |
||||||
|
PMU->GEN_PURPOSE_0 = FB_CFG_DISABLE; |
||||||
|
PIF->CFG_CTL = CFG_CTL_LOAD_DISABLE; |
||||||
|
PMU->FB_ISOLATION = FB_ISOLATION_DISABLE; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int eos_s3_fpga_init(const struct device *dev) |
||||||
|
{ |
||||||
|
IO_MUX->PAD_19_CTRL = PAD_ENABLE; |
||||||
|
|
||||||
|
struct quickfeather_fpga_data *data = dev->data; |
||||||
|
|
||||||
|
data->FPGA_info = FPGA_INFO; |
||||||
|
|
||||||
|
eos_s3_fpga_reset(dev); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static struct quickfeather_fpga_data fpga_data; |
||||||
|
|
||||||
|
static const struct fpga_driver_api eos_s3_api = { |
||||||
|
.reset = eos_s3_fpga_reset, |
||||||
|
.load = eos_s3_fpga_load, |
||||||
|
.get_status = eos_s3_fpga_get_status, |
||||||
|
.on = eos_s3_fpga_on, |
||||||
|
.off = eos_s3_fpga_off, |
||||||
|
.get_info = eos_s3_fpga_get_info |
||||||
|
}; |
||||||
|
|
||||||
|
DEVICE_DEFINE(fpga, "FPGA", &eos_s3_fpga_init, NULL, &fpga_data, NULL, APPLICATION, |
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &eos_s3_api); |
@ -0,0 +1,73 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Antmicro <www.antmicro.com> |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef ZEPHYR_DRIVERS_FPGA_EOS_S3_H_ |
||||||
|
#define ZEPHYR_DRIVERS_FPGA_EOS_S3_H_ |
||||||
|
|
||||||
|
#include <eoss3_dev.h> |
||||||
|
|
||||||
|
struct PIF_struct { |
||||||
|
/* Fabric Configuration Control Register, offset: 0x000 */ |
||||||
|
__IO uint32_t CFG_CTL; |
||||||
|
/* Maximum Bit Length Count, offset: 0x004 */ |
||||||
|
__IO uint32_t MAX_BL_CNT; |
||||||
|
/* Maximum Word Length Count, offset: 0x008 */ |
||||||
|
__IO uint32_t MAX_WL_CNT; |
||||||
|
uint32_t reserved[1020]; |
||||||
|
/* Configuration Data, offset: 0xFFC */ |
||||||
|
__IO uint32_t CFG_DATA; |
||||||
|
}; |
||||||
|
|
||||||
|
#define PIF ((struct PIF_struct *)PIF_CTRL_BASE) |
||||||
|
|
||||||
|
#define FB_CFG_ENABLE ((uint32_t)(0x00000200)) |
||||||
|
#define FB_CFG_DISABLE ((uint32_t)(0x00000000)) |
||||||
|
|
||||||
|
#define CFG_CTL_APB_CFG_WR ((uint32_t)(0x00008000)) |
||||||
|
#define CFG_CTL_APB_CFG_RD ((uint32_t)(0x00004000)) |
||||||
|
#define CFG_CTL_APB_WL_DIN ((uint32_t)(0x00003C00)) |
||||||
|
#define CFG_CTL_APB_PARTIAL_LOAD ((uint32_t)(0x00000200)) |
||||||
|
#define CFG_CTL_APB_BL_SEL ((uint32_t)(0x00000100)) |
||||||
|
#define CFG_CTL_APB_BLM_SEL ((uint32_t)(0x00000080)) |
||||||
|
#define CFG_CTL_APB_BR_SEL ((uint32_t)(0x00000040)) |
||||||
|
#define CFG_CTL_APB_BRM_SEL ((uint32_t)(0x00000020)) |
||||||
|
#define CFG_CTL_APB_TL_SEL ((uint32_t)(0x00000010)) |
||||||
|
#define CFG_CTL_APB_TLM_SEL ((uint32_t)(0x00000008)) |
||||||
|
#define CFG_CTL_APB_TR_SEL ((uint32_t)(0x00000004)) |
||||||
|
#define CFG_CTL_APB_TRM_SEL ((uint32_t)(0x00000002)) |
||||||
|
#define CFG_CTL_APB_SEL_CFG ((uint32_t)(0x00000001)) |
||||||
|
|
||||||
|
#define FB_ISOLATION_ENABLE ((uint32_t)(0x00000001)) |
||||||
|
#define FB_ISOLATION_DISABLE ((uint32_t)(0x00000000)) |
||||||
|
|
||||||
|
#define PMU_FFE_FB_PF_SW_PD_FB_PD ((uint32_t)(0x00000002)) |
||||||
|
#define PMU_FB_PWR_MODE_CFG_FB_SD ((uint32_t)(0x00000002)) |
||||||
|
#define PMU_FB_PWR_MODE_CFG_FB_DP ((uint32_t)(0x00000001)) |
||||||
|
|
||||||
|
#define FPGA_INFO \ |
||||||
|
"eos_s3 eFPGA features:\n" \ |
||||||
|
"891 Logic Cells\n" \ |
||||||
|
"8 FIFO Controllers\n" \ |
||||||
|
"32 Configurable Interfaces\n" \ |
||||||
|
"2x32x32(or 4x16x16) Multiplier\n" \ |
||||||
|
"64Kbit SRAM\n" |
||||||
|
|
||||||
|
#define PAD_ENABLE \ |
||||||
|
(PAD_E_4MA | PAD_P_PULLDOWN | PAD_OEN_NORMAL | PAD_SMT_DISABLE | PAD_REN_DISABLE | \ |
||||||
|
PAD_SR_SLOW | PAD_CTRL_SEL_AO_REG) |
||||||
|
|
||||||
|
#define PAD_DISABLE \ |
||||||
|
(PAD_SMT_DISABLE | PAD_REN_DISABLE | PAD_SR_SLOW | PAD_E_4MA | PAD_P_PULLDOWN | \ |
||||||
|
PAD_OEN_NORMAL | PAD_CTRL_SEL_AO_REG) |
||||||
|
|
||||||
|
#define CFG_CTL_LOAD_ENABLE \ |
||||||
|
(CFG_CTL_APB_CFG_WR | CFG_CTL_APB_WL_DIN | CFG_CTL_APB_BL_SEL | CFG_CTL_APB_BLM_SEL | \ |
||||||
|
CFG_CTL_APB_BR_SEL | CFG_CTL_APB_BRM_SEL | CFG_CTL_APB_TL_SEL | CFG_CTL_APB_TLM_SEL | \ |
||||||
|
CFG_CTL_APB_TR_SEL | CFG_CTL_APB_TRM_SEL | CFG_CTL_APB_SEL_CFG) |
||||||
|
|
||||||
|
#define CFG_CTL_LOAD_DISABLE 0 |
||||||
|
|
||||||
|
#endif /* ZEPHYR_DRIVERS_FPGA_EOS_S3_H_ */ |
@ -0,0 +1,7 @@ |
|||||||
|
# SPDX-License-Identifier: Apache-2.0 |
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.13) |
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) |
||||||
|
project(fpga_controller) |
||||||
|
|
||||||
|
target_sources(app PRIVATE src/main.c) |
@ -0,0 +1,21 @@ |
|||||||
|
# Zephyr FPGA controller |
||||||
|
This module is an FPGA driver that can easily load a bitstream, reset it, check its status, enable or disable the FPGA. |
||||||
|
This sample demonstrates how to use the FPGA driver API. |
||||||
|
Currently the sample works with [Quicklogic Quickfeather board](https://github.com/QuickLogic-Corp/quick-feather-dev-board). |
||||||
|
|
||||||
|
## Requirements |
||||||
|
* Zephyr RTOS |
||||||
|
* [Quicklogic Quickfeather board](https://github.com/QuickLogic-Corp/quick-feather-dev-board) |
||||||
|
|
||||||
|
## Building |
||||||
|
|
||||||
|
For the QuickLogic QuickFeather board: |
||||||
|
```bash |
||||||
|
west build -b quick_feather samples/drivers/fpga/fpga_controller |
||||||
|
``` |
||||||
|
|
||||||
|
## Running |
||||||
|
See [QuickFeather programming and debugging](https://docs.zephyrproject.org/latest/boards/arm/quick_feather/doc/index.html#programming-and-debugging) on how to load an image to the board. |
||||||
|
|
||||||
|
## Sample output |
||||||
|
Once the board is programmed, the LED should alternately flash red and green. |
@ -0,0 +1,2 @@ |
|||||||
|
CONFIG_FPGA=y |
||||||
|
CONFIG_EOS_S3_FPGA=y |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,41 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Antmicro <www.antmicro.com> |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <zephyr.h> |
||||||
|
#include <device.h> |
||||||
|
#include <sys/printk.h> |
||||||
|
#include <drivers/fpga.h> |
||||||
|
#include "redled.h" |
||||||
|
#include "greenled.h" |
||||||
|
#include <eoss3_dev.h> |
||||||
|
|
||||||
|
const struct device *fpga; |
||||||
|
|
||||||
|
void main(void) |
||||||
|
{ |
||||||
|
IO_MUX->PAD_21_CTRL = (PAD_E_4MA | PAD_P_PULLDOWN | PAD_OEN_NORMAL | |
||||||
|
PAD_SMT_DISABLE | PAD_REN_DISABLE | PAD_SR_SLOW | |
||||||
|
PAD_CTRL_SEL_AO_REG); /* Enable red led */ |
||||||
|
IO_MUX->PAD_22_CTRL = (PAD_E_4MA | PAD_P_PULLDOWN | PAD_OEN_NORMAL | |
||||||
|
PAD_SMT_DISABLE | PAD_REN_DISABLE | PAD_SR_SLOW | |
||||||
|
PAD_CTRL_SEL_AO_REG); /* Enable green led */ |
||||||
|
|
||||||
|
fpga = device_get_binding("FPGA"); |
||||||
|
|
||||||
|
if (!fpga) { |
||||||
|
printk("unable to find fpga device\n"); |
||||||
|
} |
||||||
|
while (1) { |
||||||
|
fpga_load(fpga, axFPGABitStream_red, |
||||||
|
sizeof(axFPGABitStream_red)); |
||||||
|
k_msleep(2000); |
||||||
|
fpga_reset(fpga); |
||||||
|
fpga_load(fpga, axFPGABitStream_green, |
||||||
|
sizeof(axFPGABitStream_green)); |
||||||
|
k_msleep(2000); |
||||||
|
fpga_reset(fpga); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue