mpfs/mpfs_rcc: Add stub driver for FPGA clock and reset controller

This patch adds a driver framework to control individual FPGA reset and
clock gates.

For FPGA devices, only the fabric (FIC0/FIC1/FIC3) clock and reset can be
controlled, which affects the whole fabric / domain. This is problematic
for obvious reasons.

For MSS peripherals, clocks and reset are controlled individually for each
peripheral via MSS memory mapped registers (MPFS_SYSREG). To get the same
capability for FPGA peripherals, the same controller needs to be
fabricated on the FPGA.

However, the FPGA clock/reset controller is entirely user dependent, so a
generic implementation is not possible. However, a generic driver is
needed in order to build the current FPGA peripheral drivers. A stub
implementation of the driver is provided in order to achieve this.

Signed-off-by: Ville Juven <ville.juven@unikie.com>
This commit is contained in:
Ville Juven
2025-03-20 13:42:45 +02:00
committed by Alan C. Assis
parent 10d46929b9
commit 25e7b48c7e
8 changed files with 271 additions and 1 deletions
+6
View File
@@ -828,6 +828,12 @@ config MPFS_MPUCFG
---help---
Enable driver to set MPUCFG entries.
config MPFS_RCC
bool "Enable Reset and Clock Controller (RCC) driver"
default y
---help---
Enable driver for reset / clock controller.
config MPFS_HAVE_CORERMII
bool "CoreRMII FPGA IP block configured"
default n
+3
View File
@@ -122,3 +122,6 @@ ifeq ($(CONFIG_MPFS_MPUCFG),y)
CHIP_CSRCS += mpfs_mpu.c
endif
ifeq ($(CONFIG_MPFS_RCC),y)
CHIP_CSRCS += mpfs_rcc.c
endif
@@ -137,6 +137,11 @@
#define MPFS_SYSREG_SPARE_PERIM_RW_OFFSET 0x02DC /* Spare signal back to G5C */
#define MPFS_SYSREG_SPARE_FIC_OFFSET 0x02E0 /* Unused FIC resets */
#define MPFS_SYSREG_SOFT_RESET_CR (MPFS_SYSREG_BASE + \
MPFS_SYSREG_SOFT_RESET_CR_OFFSET)
#define MPFS_SYSREG_SUBBLK_CLOCK_CR (MPFS_SYSREG_BASE + \
MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET)
/* Register bit field definitions *******************************************/
/* CLOCK_CONFIG_CR:
+25 -1
View File
@@ -44,7 +44,11 @@
#include <arch/board/board.h>
#include "mpfs_rcc.h"
#include "hardware/mpfs_memorymap.h"
#include "hardware/mpfs_corepwm.h"
#include "hardware/mpfs_sysreg.h"
#include "riscv_internal.h"
/****************************************************************************
@@ -752,6 +756,25 @@ static int pwm_ioctl(struct pwm_lowerhalf_s *dev, int cmd,
return -ENOTTY;
}
static int pwm_init(struct mpfs_pwmtimer_s *priv)
{
/* Toggle peripheral reset */
mpfs_set_reset(MPFS_RCC_I2C, priv->pwmid, 1);
mpfs_set_reset(MPFS_RCC_I2C, priv->pwmid, 0);
/* Release FIC reset and enable clocks */
modifyreg32(MPFS_SYSREG_SOFT_RESET_CR,
SYSREG_SOFT_RESET_CR_FIC3 | SYSREG_SOFT_RESET_CR_FPGA,
0);
modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0,
SYSREG_SUBBLK_CLOCK_CR_FIC3);
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -795,6 +818,7 @@ struct pwm_lowerhalf_s *mpfs_corepwm_init(int pwmid)
return NULL;
}
pwm_init(lower);
return (struct pwm_lowerhalf_s *)lower;
}
+6
View File
@@ -44,6 +44,7 @@
#include "mpfs_gpio.h"
#include "mpfs_corespi.h"
#include "mpfs_rcc.h"
#include "hardware/mpfs_corespi.h"
#include "hardware/mpfs_sysreg.h"
#include "riscv_internal.h"
@@ -1513,6 +1514,11 @@ static void mpfs_spi_init(struct spi_dev_s *dev)
up_disable_irq(priv->plic_irq);
/* Toggle peripheral reset */
mpfs_set_reset(MPFS_RCC_SPI, priv->id, 1);
mpfs_set_reset(MPFS_RCC_SPI, priv->id, 0);
/* Release FIC reset and enable clocks */
modifyreg32(MPFS_SYSREG_SOFT_RESET_CR,
+6
View File
@@ -48,6 +48,7 @@
#include "mpfs_gpio.h"
#include "mpfs_i2c.h"
#include "mpfs_rcc.h"
#include "riscv_internal.h"
#include "hardware/mpfs_i2c.h"
@@ -369,6 +370,11 @@ static int mpfs_i2c_init(struct mpfs_i2c_priv_s *priv)
if (priv->fpga)
{
/* Toggle peripheral reset */
mpfs_set_reset(MPFS_RCC_I2C, priv->id, 1);
mpfs_set_reset(MPFS_RCC_I2C, priv->id, 0);
/* FIC3 is used by many, don't reset it here, or many
* FPGA based modules will stop working right here. Just
* bring out of reset instead.
+99
View File
@@ -0,0 +1,99 @@
/****************************************************************************
* arch/risc-v/src/mpfs/mpfs_rcc.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/spinlock.h>
#include <errno.h>
#include <sys/types.h>
#include "mpfs_rcc.h"
#include "mpfs_memorymap.h"
#include "riscv_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: mpfs_set_reset
*
* Description:
* Enable / disable peripheral reset.
*
* Input Parameters:
* rcc_id - Device id.
* instance - Optional instance number for device.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure.
*
****************************************************************************/
int mpfs_set_reset(int rcc_id, int instance, bool state)
{
return -ENODEV;
}
/****************************************************************************
* Name: mpfs_set_clock
*
* Description:
* Enable / disable peripheral clock.
*
* Input Parameters:
* rcc_id - Device id.
* instance - Optional instance number for device.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure.
*
****************************************************************************/
int mpfs_set_clock(int rcc_id, int instance, bool state)
{
return -ENODEV;
}
+121
View File
@@ -0,0 +1,121 @@
/****************************************************************************
* arch/risc-v/src/mpfs/mpfs_rcc.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef ARCH_RISC_V_SRC_MPFS_MPFS_RCC_H
#define ARCH_RISC_V_SRC_MPFS_MPFS_RCC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
enum mpfs_rcc_id_e
{
MPFS_RCC_CAN,
MPFS_RCC_I2C,
MPFS_RCC_PWM,
MPFS_RCC_SPI,
MPFS_RCC_UART,
MPFS_RCC_LAST,
};
#ifndef __ASSEMBLY__
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: mpfs_set_reset
*
* Description:
* Enable / disable peripheral reset.
*
* Input Parameters:
* rcc_id - Device id.
* instance - Optional instance number for device.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure.
*
****************************************************************************/
#ifdef CONFIG_MPFS_RCC
int mpfs_set_reset(int rcc_id, int instance, bool state);
#else
# define mpfs_set_reset(rcc_id, instance, state) (0)
#endif
/****************************************************************************
* Name: mpfs_set_clock
*
* Description:
* Enable / disable peripheral clock.
*
* Input Parameters:
* rcc_id - Device id.
* instance - Optional instance number for device.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure.
*
****************************************************************************/
#ifdef CONFIG_MPFS_RCC
int mpfs_set_clock(int rcc_id, int instance, bool state);
#else
# define mpfs_set_clock(rcc_id, instance, state) (0)
#endif
#if defined(__cplusplus)
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* ARCH_RISC_V_SRC_MPFS_MPFS_RCC_H */