Commit e1772409 authored by Ioannis Karachalios's avatar Ioannis Karachalios Committed by Anas Nashif
Browse files

drivers: clock_control: smartbond: Add support for the memc driver.



1. Update the clock control driver so it can update timing settings for
   QSPIC2 following system clock transitions (translated based on
   AHB AMBA bus clock).
2. Remove the QSPIC related subroutines and use the respective HAL API
   which is now available.
3. Add support for PM (CONFIG_PM_DEVICE). This is required as QSPIC2
   register file is powered by PD_SYS which is turned off during device
   sleep and so registers contents are lost (in contrast to QSPIC which
   is used to drive the flash memory).

Signed-off-by: default avatarIoannis Karachalios <ioannis.karachalios.px@renesas.com>
parent 02e73987
Loading
Loading
Loading
Loading
+64 −37
Original line number Diff line number Diff line
@@ -10,7 +10,9 @@
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/smartbond_clock_control.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include <da1469x_clock.h>
#include <da1469x_qspic.h>

LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL);

@@ -321,30 +323,6 @@ static void smartbond_clock_control_off_by_ord(const struct device *dev,
	smartbond_clock_control_off(dev, (clock_control_subsys_rate_t)clk);
}

static void
qspi_set_read_pipe_delay(uint8_t delay)
{
	QSPIC->QSPIC_CTRLMODE_REG =
		(QSPIC->QSPIC_CTRLMODE_REG & ~QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Msk) |
		(delay << QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Pos) |
		QSPIC_QSPIC_CTRLMODE_REG_QSPIC_RPIPE_EN_Msk;
}

static void
qspi_set_cs_delay(uint32_t sys_clock_freq, uint32_t read_delay_ns, uint32_t erase_delay_ns)
{
	sys_clock_freq /= 100000;
	uint32_t read_delay_cyc = ((read_delay_ns * sys_clock_freq) + 9999) / 10000;
	uint32_t erase_delay_cyc = ((erase_delay_ns * sys_clock_freq) + 9999) / 10000;

	QSPIC->QSPIC_BURSTCMDB_REG =
		(QSPIC->QSPIC_BURSTCMDB_REG & ~QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Msk) |
		read_delay_cyc << QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Pos;
	QSPIC->QSPIC_ERASECMDB_REG =
		(QSPIC->QSPIC_ERASECMDB_REG & ~QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Msk) |
		(erase_delay_cyc << QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Pos);
}

int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk)
{
	int rc = 0;
@@ -385,6 +363,33 @@ int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk)
	return rc;
}

static void smartbond_clock_control_update_memory_settings(uint32_t sys_clock_freq)
{
	if (sys_clock_freq > 32000000) {
		da1469x_qspi_set_read_pipe_delay(QSPIC_ID, 7);
#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay)
		da1469x_qspi_set_read_pipe_delay(QSPIC2_ID, 7);
#endif
	} else {
		da1469x_qspi_set_read_pipe_delay(QSPIC_ID, 2);
#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay)
		da1469x_qspi_set_read_pipe_delay(QSPIC2_ID, 2);
#endif
	}

	da1469x_qspi_set_cs_delay(QSPIC_ID, SystemCoreClock,
		DT_PROP(DT_NODELABEL(flash_controller), read_cs_idle_delay),
		DT_PROP(DT_NODELABEL(flash_controller), erase_cs_idle_delay));
#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay)
	da1469x_qspi_set_cs_delay(QSPIC2_ID, SystemCoreClock,
		DT_PROP(DT_NODELABEL(memc), read_cs_idle_min_ns),
		DT_PROP_OR(DT_NODELABEL(memc), erase_cs_idle_min_ns, 0));
#if DT_PROP(DT_NODELABEL(memc), is_ram)
	da1469x_qspi_set_tcem(SystemCoreClock, DT_PROP(DT_NODELABEL(memc), tcem_max_us));
#endif
#endif
}

int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk)
{
	uint32_t sys_clock_freq;
@@ -399,12 +404,7 @@ int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk)

	/* When PLL is selected as system clock qspi read pipe delay must be set to 7 */
	if (sys_clock_freq > 32000000) {
		qspi_set_read_pipe_delay(7);
		qspi_set_cs_delay(SystemCoreClock,
				  DT_PROP(DT_NODELABEL(flash_controller),
					  read_cs_idle_delay),
				  DT_PROP(DT_NODELABEL(flash_controller),
					  erase_cs_idle_delay));
		smartbond_clock_control_update_memory_settings(sys_clock_freq);
	}

	if (sys_clk == SMARTBOND_CLK_RC32M) {
@@ -420,12 +420,7 @@ int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk)

	/* When switching back from PLL to 32MHz read pipe delay may be set to 2 */
	if (SystemCoreClock <= 32000000) {
		qspi_set_read_pipe_delay(2);
		qspi_set_cs_delay(SystemCoreClock,
				  DT_PROP(DT_NODELABEL(flash_controller),
					  read_cs_idle_delay),
				  DT_PROP(DT_NODELABEL(flash_controller),
					  erase_cs_idle_delay));
		smartbond_clock_control_update_memory_settings(SystemCoreClock);
	}

	return 0;
@@ -449,6 +444,11 @@ int smartbond_clocks_init(const struct device *dev)

	ARG_UNUSED(dev);

#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay)
	/* Make sure QSPIC2 is enabled */
	da1469x_clock_amba_enable(CRG_TOP_CLK_AMBA_REG_QSPI2_ENABLE_Msk);
#endif

#define ENABLE_OSC(clock) smartbond_clock_control_on_by_ord(dev, DT_DEP_ORD(clock))
#define DISABLE_OSC(clock) if (DT_NODE_HAS_STATUS(clock, disabled)) { \
		smartbond_clock_control_off_by_ord(dev, DT_DEP_ORD(clock)); \
@@ -488,9 +488,36 @@ static struct clock_control_driver_api smartbond_clock_control_api = {
	.get_rate = smartbond_clock_control_get_rate,
};

#if CONFIG_PM_DEVICE
static int smartbond_clocks_pm_action(const struct device *dev, enum pm_device_action action)
{
	switch (action) {
	case PM_DEVICE_ACTION_SUSPEND:
		break;
	case PM_DEVICE_ACTION_RESUME:
#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay)
		/* Make sure QSPIC2 is enabled */
		da1469x_clock_amba_enable(CRG_TOP_CLK_AMBA_REG_QSPI2_ENABLE_Msk);
#endif
		/*
		 * Make sure the flash controller has correct settings as clock restoration
		 * might have been performed upon waking up.
		 */
		smartbond_clock_control_update_memory_settings(SystemCoreClock);
		break;
	default:
		return -ENOTSUP;
	}

	return 0;
}
#endif

PM_DEVICE_DT_DEFINE(DT_NODELABEL(osc), smartbond_clocks_pm_action);

DEVICE_DT_DEFINE(DT_NODELABEL(osc),
		 &smartbond_clocks_init,
		 NULL,
		 PM_DEVICE_DT_GET(DT_NODELABEL(osc)),
		 NULL, NULL,
		 PRE_KERNEL_1,
		 CONFIG_CLOCK_CONTROL_INIT_PRIORITY,