aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Royer <nroyer@baylibre.com>2020-09-27 17:47:17 +0200
committernicola-mazzucato-arm <42373140+nicola-mazzucato-arm@users.noreply.github.com>2020-10-15 17:45:38 +0100
commit7ad0b7b11b52e8898852f7fbc2c41d7c37d59809 (patch)
treeef3428ffa0514616e1d3461f2538220b1d6017f7
parentc96ddcce819116effc4f61d0bddc65aa56c99f6e (diff)
rcar/module: add rcar sd_clock module and config data
Change-Id: I3c1d31d82a6bdd8ad490ff1f0e609d93ebcd5da0 Signed-off-by: Tsutomu Muroya <tsutomu.muroya.jy@bp.renesas.com> Signed-off-by: Nicolas Royer <nroyer@baylibre.com>
-rw-r--r--product/rcar/module/rcar_sd_clock/include/mod_rcar_sd_clock.h271
-rw-r--r--product/rcar/module/rcar_sd_clock/src/Makefile11
-rw-r--r--product/rcar/module/rcar_sd_clock/src/mod_rcar_sd_clock.c422
-rw-r--r--product/rcar/scp_ramfw/config_rcar_sd_clock.c658
4 files changed, 1362 insertions, 0 deletions
diff --git a/product/rcar/module/rcar_sd_clock/include/mod_rcar_sd_clock.h b/product/rcar/module/rcar_sd_clock/include/mod_rcar_sd_clock.h
new file mode 100644
index 00000000..8e3c45ce
--- /dev/null
+++ b/product/rcar/module/rcar_sd_clock/include/mod_rcar_sd_clock.h
@@ -0,0 +1,271 @@
+/*
+ * Renesas SCP/MCP Software
+ * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOD_RCAR_SD_CLOCK_H
+#define MOD_RCAR_SD_CLOCK_H
+
+#include <clock_sd_devices.h>
+#include <rcar_mmap.h>
+
+#include <mod_clock.h>
+#include <mod_rcar_clock.h>
+
+#include <fwk_element.h>
+
+#include <stdint.h>
+
+/*!
+ * \addtogroup GroupRCARModule RCAR Product Modules
+ * @{
+ */
+
+/*!
+ * \defgroup GroupRCARSdClock SD clock
+ * @{
+ */
+
+/*!
+ * \brief Rate lookup entry.
+ */
+struct mod_rcar_sd_clock_rate {
+ /*! Divider used to obtain the rate value. */
+ uint32_t divider_num;
+ /*! Value to be set for the divider. */
+ uint32_t divider;
+ /*! Divider maskbit value. */
+ uint32_t divider_mask;
+};
+
+/*!
+ * \brief Subsystem clock device configuration.
+ */
+struct mod_rcar_sd_clock_dev_config {
+ /*! The type of the clock device. */
+ enum mod_rcar_clock_type type;
+
+ /*! Pointer to the clock's control register. */
+ volatile uint32_t const control_reg;
+
+ /*! enable / disable bit position. */
+ volatile bool stop_clk;
+
+ /*! enable / disable bit position. */
+ volatile uint32_t const stop_clk_bit;
+
+ /*! Parent clock id. */
+ uint32_t parent;
+
+ /*! Required initialization Clock divider. */
+ bool need_hardware_init;
+
+ /*! Fixed Clock divider. */
+ uint32_t div;
+
+ /*! Fixed Clock divider. */
+ uint32_t multi;
+
+ /*! The type of rates the clock provides (discrete or continuous) */
+ enum mod_clock_rate_type rate_type;
+
+ /*! Pointer to the clock's rate lookup table. */
+ const struct mod_rcar_sd_clock_rate *rate_table;
+
+ /*! The number of rates in the rate lookup table. */
+ uint32_t rate_count;
+};
+
+/*!
+ * @cond
+ */
+
+/* Device context */
+struct rcar_sd_clock_dev_ctx {
+ bool initialized;
+ uint64_t current_rate;
+ uint64_t *rate_table;
+ enum mod_clock_state current_state;
+ const struct mod_rcar_sd_clock_dev_config *config;
+};
+
+/* Module context */
+struct rcar_sd_clock_ctx {
+ struct rcar_sd_clock_dev_ctx *dev_ctx_table;
+ unsigned int dev_count;
+ uint32_t parent_clk[CLOCK_PARENT_IDX_COUNT];
+};
+
+struct rcar_gen3_cpg_pll_config {
+ char extal_div;
+ char pll1_mult;
+ char pll1_div;
+ char pll3_mult;
+ char pll3_div;
+ char osc_prediv;
+};
+
+/* control register */
+#define CPG_SD0CKCR (CPG_BASE + 0x0074)
+#define CPG_SD1CKCR (CPG_BASE + 0x0078)
+#define CPG_SD2CKCR (CPG_BASE + 0x0268)
+#define CPG_SD3CKCR (CPG_BASE + 0x026C)
+#define CPG_SDNCKCR_MASK 0x1F
+#define CPG_SDNCKCR_SD_64 0x11
+#define CPG_SDNCKCR_SD_32 0xD
+#define CPG_SDNCKCR_SD_16 0x9
+#define CPG_SDNCKCR_SD_8 0x5
+#define CPG_SDNCKCR_SD_4 0x1
+#define CPG_SDNCKCR_SD_2 0x0
+
+#define CPG_CANFDCKCR (CPG_BASE + 0x0244)
+#define CPG_CSI0CKCR (CPG_BASE + 0x000C)
+#define CPG_MSOCKCR (CPG_BASE + 0x0014)
+#define CPG_HDMICKCR (CPG_BASE + 0x0250)
+#define CPG_CON_MASK 0x3F
+#define CPG_CON_MAX 64
+
+#define CPG_FRQCRB_ZTRFC_MASK 0xF00000
+#define CPG_FRQCRB_ZTRFC_24 0x800000
+#define CPG_FRQCRB_ZTRFC_18 0x700000
+#define CPG_FRQCRB_ZTRFC_16 0x600000
+#define CPG_FRQCRB_ZTRFC_12 0x500000
+#define CPG_FRQCRB_ZTRFC_8 0x400000
+#define CPG_FRQCRB_ZTRFC_6 0x300000
+#define CPG_FRQCRB_ZTFC_MASK 0xF0000
+#define CPG_FRQCRB_ZTFC_24 0x80000
+#define CPG_FRQCRB_ZTFC_18 0x70000
+#define CPG_FRQCRB_ZTFC_16 0x60000
+#define CPG_FRQCRB_ZTFC_12 0x50000
+#define CPG_FRQCRB_ZTFC_8 0x40000
+#define CPG_FRQCRB_ZTFC_6 0x30000
+#define CPG_FRQCRB_ZTFC_4 0x20000
+#define CPG_FRQCRB_ZTRD2FC_MASK 0xF
+#define CPG_FRQCRB_ZTRD2FC_24 0x8
+#define CPG_FRQCRB_ZTRD2FC_18 0x7
+#define CPG_FRQCRB_ZTRD2FC_16 0x6
+#define CPG_FRQCRB_ZTRD2FC_12 0x5
+
+#define CPG_PLL_CONFIG_INDEX(md) \
+ ((((md)&BIT(14)) >> 11) | (((md)&BIT(13)) >> 11) | \
+ (((md)&BIT(19)) >> 18) | (((md)&BIT(17)) >> 17))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */
+ {
+ 1,
+ 192,
+ 1,
+ 192,
+ 1,
+ 16,
+ },
+ {
+ 1,
+ 192,
+ 1,
+ 128,
+ 1,
+ 16,
+ },
+ { 0, /* Prohibited setting */ },
+ {
+ 1,
+ 192,
+ 1,
+ 192,
+ 1,
+ 16,
+ },
+ {
+ 1,
+ 160,
+ 1,
+ 160,
+ 1,
+ 19,
+ },
+ {
+ 1,
+ 160,
+ 1,
+ 106,
+ 1,
+ 19,
+ },
+ { 0, /* Prohibited setting */ },
+ {
+ 1,
+ 160,
+ 1,
+ 160,
+ 1,
+ 19,
+ },
+ {
+ 1,
+ 128,
+ 1,
+ 128,
+ 1,
+ 24,
+ },
+ {
+ 1,
+ 128,
+ 1,
+ 84,
+ 1,
+ 24,
+ },
+ { 0, /* Prohibited setting */ },
+ {
+ 1,
+ 128,
+ 1,
+ 128,
+ 1,
+ 24,
+ },
+ {
+ 2,
+ 192,
+ 1,
+ 192,
+ 1,
+ 32,
+ },
+ {
+ 2,
+ 192,
+ 1,
+ 128,
+ 1,
+ 32,
+ },
+ { 0, /* Prohibited setting */ },
+ {
+ 2,
+ 192,
+ 1,
+ 192,
+ 1,
+ 32,
+ },
+};
+
+/*!
+ * @endcond
+ */
+
+/*!
+ * @}
+ */
+
+/*!
+ * @}
+ */
+
+#endif /* MOD_RCAR_SD_CLOCK_H */
diff --git a/product/rcar/module/rcar_sd_clock/src/Makefile b/product/rcar/module/rcar_sd_clock/src/Makefile
new file mode 100644
index 00000000..998cc590
--- /dev/null
+++ b/product/rcar/module/rcar_sd_clock/src/Makefile
@@ -0,0 +1,11 @@
+#
+# Renesas SCP/MCP Software
+# Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BS_LIB_NAME := RCAR SD Clock Driver
+BS_LIB_SOURCES := mod_rcar_sd_clock.c
+
+include $(BS_DIR)/lib.mk
diff --git a/product/rcar/module/rcar_sd_clock/src/mod_rcar_sd_clock.c b/product/rcar/module/rcar_sd_clock/src/mod_rcar_sd_clock.c
new file mode 100644
index 00000000..a6bfc83d
--- /dev/null
+++ b/product/rcar/module/rcar_sd_clock/src/mod_rcar_sd_clock.c
@@ -0,0 +1,422 @@
+/*
+ * Renesas SCP/MCP Software
+ * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <clock_sd_devices.h>
+#include <mmio.h>
+
+#include <mod_clock.h>
+#include <mod_rcar_power_domain.h>
+#include <mod_rcar_sd_clock.h>
+
+#include <fwk_assert.h>
+#include <fwk_element.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <fwk_module_idx.h>
+#include <fwk_status.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+
+static struct rcar_sd_clock_ctx module_ctx;
+
+/*
+ * Static helper functions
+ */
+static int get_rate_entry(
+ struct rcar_sd_clock_dev_ctx *ctx,
+ uint64_t target_rate,
+ struct mod_rcar_sd_clock_rate **entry)
+{
+ struct mod_rcar_sd_clock_rate *rate_entry;
+ uint32_t cnt;
+ if (ctx == NULL)
+ return FWK_E_PARAM;
+ if (entry == NULL)
+ return FWK_E_PARAM;
+
+ /* Perform a binary search to find the entry matching the requested rate */
+ if (ctx->config->rate_type == MOD_CLOCK_RATE_TYPE_CONTINUOUS) {
+ if ((ctx->rate_table[0] > target_rate) &&
+ (ctx->rate_table[1] < target_rate))
+ return FWK_E_PARAM;
+ rate_entry = (struct mod_rcar_sd_clock_rate *)ctx->config->rate_table;
+ *entry = rate_entry;
+ } else {
+ for (cnt = 0; cnt < ctx->config->rate_count; cnt++) {
+ if (ctx->rate_table[cnt] == target_rate)
+ break;
+ }
+
+ if (cnt >= ctx->config->rate_count)
+ return FWK_E_PARAM;
+ *entry = (struct mod_rcar_sd_clock_rate *)&ctx->config->rate_table[cnt];
+ }
+ return FWK_SUCCESS;
+}
+
+static int do_sd_clock_set_rate(fwk_id_t dev_id, uint64_t rate)
+{
+ int status;
+ struct rcar_sd_clock_dev_ctx *ctx;
+ struct mod_rcar_sd_clock_rate *rate_entry;
+ uint32_t value;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
+
+ status = get_rate_entry(ctx, rate, &rate_entry);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ switch (ctx->config->type) {
+ case MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE:
+ return FWK_E_SUPPORT;
+ case MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE:
+ if (ctx->config->rate_type == MOD_CLOCK_RATE_TYPE_DISCRETE) {
+ value = mmio_read_32(ctx->config->control_reg);
+ value &= (~rate_entry->divider_mask);
+ value |= rate_entry->divider;
+ mmio_write_32(ctx->config->control_reg, value);
+ } else {
+ value = mmio_read_32(ctx->config->control_reg);
+ value &= (~CPG_CON_MASK);
+ value |= (CPG_CON_MAX - (rate / ctx->rate_table[2])) & CPG_CON_MASK;
+ mmio_write_32(ctx->config->control_reg, value);
+ }
+ break;
+ default:
+ return FWK_E_SUPPORT;
+ }
+
+ ctx->current_rate = rate;
+
+ return FWK_SUCCESS;
+}
+
+/*
+ * Clock driver API functions
+ */
+static int sd_clock_set_rate(
+ fwk_id_t dev_id,
+ uint64_t rate,
+ enum mod_clock_round_mode round_mode)
+{
+ struct rcar_sd_clock_dev_ctx *ctx;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
+
+ if (!ctx->initialized)
+ return FWK_E_INIT;
+
+ if (ctx->current_state == MOD_CLOCK_STATE_STOPPED)
+ return FWK_E_PWRSTATE;
+
+ return do_sd_clock_set_rate(dev_id, rate);
+}
+
+static int sd_clock_get_rate(fwk_id_t dev_id, uint64_t *rate)
+{
+ struct rcar_sd_clock_dev_ctx *ctx;
+
+ if (rate == NULL)
+ return FWK_E_PARAM;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
+
+ *rate = ctx->current_rate;
+
+ return FWK_SUCCESS;
+}
+
+static int sd_clock_get_rate_from_index(
+ fwk_id_t dev_id,
+ unsigned int rate_index,
+ uint64_t *rate)
+{
+ struct rcar_sd_clock_dev_ctx *ctx;
+
+ if (rate == NULL)
+ return FWK_E_PARAM;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
+
+ if (rate_index >= ctx->config->rate_count)
+ return FWK_E_PARAM;
+
+ *rate = ctx->rate_table[rate_index];
+ return FWK_SUCCESS;
+}
+
+static int sd_clock_set_state(
+ fwk_id_t dev_id,
+ enum mod_clock_state target_state)
+{
+ struct rcar_sd_clock_dev_ctx *ctx;
+ uint32_t value;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
+ value = mmio_read_32(ctx->config->control_reg);
+ if (MOD_CLOCK_STATE_RUNNING == target_state)
+ value &= ~(BIT(ctx->config->stop_clk_bit));
+ else
+ value |= BIT(ctx->config->stop_clk_bit);
+
+ mmio_write_32(ctx->config->control_reg, value);
+
+ ctx->current_state = target_state;
+
+ return FWK_SUCCESS;
+}
+
+static int sd_clock_get_state(fwk_id_t dev_id, enum mod_clock_state *state)
+{
+ struct rcar_sd_clock_dev_ctx *ctx;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
+ *state = ctx->current_state;
+ return FWK_SUCCESS;
+}
+static int sd_clock_get_range(fwk_id_t dev_id, struct mod_clock_range *range)
+{
+ struct rcar_sd_clock_dev_ctx *ctx;
+
+ if (range == NULL)
+ return FWK_E_PARAM;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
+
+ range->rate_type = ctx->config->rate_type;
+ if (ctx->config->rate_count > 0) {
+ if (MOD_CLOCK_RATE_TYPE_CONTINUOUS == range->rate_type) {
+ /* SCMI_CLOCK_RATE_FORMAT_RANGE */
+ range->min = ctx->rate_table[0];
+ range->max = ctx->rate_table[1];
+ range->step = ctx->rate_table[2];
+ } else {
+ /* SCMI_CLOCK_RATE_FORMAT_LIST */
+ range->min = ctx->rate_table[0];
+ range->max = ctx->rate_table[ctx->config->rate_count - 1];
+ }
+ }
+ range->rate_count = ctx->config->rate_count;
+
+ return FWK_SUCCESS;
+}
+
+static int sd_clock_hw_initial_set_state(
+ fwk_id_t element_id,
+ struct rcar_sd_clock_dev_ctx *ctx)
+{
+ uint32_t i = 0;
+ uint32_t value = 0;
+ uint32_t div_value = 0;
+ uint64_t rate = 0;
+
+ switch (ctx->config->type) {
+ case MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE:
+ ctx->current_state = MOD_CLOCK_STATE_RUNNING;
+ div_value = ctx->config->div;
+ break;
+ case MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE:
+ /* Maintain clock supply at startup. */
+ ctx->current_state = MOD_CLOCK_STATE_RUNNING;
+ if (ctx->config->stop_clk) {
+ if (mmio_read_32(ctx->config->control_reg) &
+ BIT(ctx->config->stop_clk_bit))
+ ctx->current_state = MOD_CLOCK_STATE_STOPPED;
+ }
+ /* Holds clock frequency at startup. */
+ if (ctx->config->rate_type == MOD_CLOCK_RATE_TYPE_DISCRETE) {
+ value = mmio_read_32(ctx->config->control_reg);
+ value &= ctx->config->rate_table[0].divider_mask;
+ for (i = 0; i < ctx->config->rate_count; i++) {
+ if (value == ctx->config->rate_table[i].divider) {
+ div_value = ctx->config->rate_table[i].divider_num;
+ break;
+ }
+ }
+ } else {
+ value = mmio_read_32(ctx->config->control_reg);
+ value &= (CPG_CON_MASK);
+ div_value = (value + 1);
+ }
+ break;
+ default:
+ return FWK_E_SUPPORT;
+ }
+ ctx->current_rate = module_ctx.parent_clk[ctx->config->parent] / div_value;
+
+ if (ctx->config->need_hardware_init) {
+ rate = module_ctx.parent_clk[ctx->config->parent] / ctx->config->div;
+ do_sd_clock_set_rate(element_id, rate);
+ }
+
+ return FWK_SUCCESS;
+}
+
+static int sd_clock_resume(void)
+{
+ fwk_id_t element_id =
+ FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLK_ID_SD_START);
+ struct rcar_sd_clock_dev_ctx *ctx;
+ uint32_t sd_id = 0;
+ int ret = FWK_SUCCESS;
+
+ for (sd_id = CLK_ID_SD_START; sd_id < CLK_ID_SD_END; sd_id++) {
+ element_id.element.element_idx = sd_id;
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id);
+
+ ret = sd_clock_hw_initial_set_state(element_id, ctx);
+ if (ret != FWK_SUCCESS)
+ break;
+ }
+ return ret;
+}
+
+static const struct mod_rcar_clock_drv_api api_clock = {
+ .set_rate = sd_clock_set_rate,
+ .get_rate = sd_clock_get_rate,
+ .get_rate_from_index = sd_clock_get_rate_from_index,
+ .set_state = sd_clock_set_state,
+ .get_state = sd_clock_get_state,
+ .get_range = sd_clock_get_range,
+ .resume = sd_clock_resume,
+};
+
+/*
+ * Framework handler functions
+ */
+
+static int r8a7795_cpg_pll1_init(uint32_t ext_rate)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ uint32_t saved_mode;
+ saved_mode = mmio_read_32(RCAR_MODEMR);
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(saved_mode)];
+ return (ext_rate * cpg_pll_config->pll1_mult / cpg_pll_config->pll1_div);
+}
+
+static int r8a7795_cpg_init(uint32_t ext_rate)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ uint32_t saved_mode;
+ saved_mode = mmio_read_32(RCAR_MODEMR);
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(saved_mode)];
+ return (ext_rate / cpg_pll_config->osc_prediv);
+}
+
+static int sd_clock_init(
+ fwk_id_t module_id,
+ unsigned int element_count,
+ const void *data)
+{
+ struct mod_ext_clock_rate *ext;
+ module_ctx.dev_count = element_count;
+
+ if (element_count == 0)
+ return FWK_SUCCESS;
+
+ module_ctx.dev_ctx_table =
+ fwk_mm_calloc(element_count, sizeof(struct rcar_sd_clock_dev_ctx));
+ if (module_ctx.dev_ctx_table == NULL)
+ return FWK_E_NOMEM;
+
+ /* Parent clock calculation. */
+ ext = (struct mod_ext_clock_rate *)data;
+ module_ctx.parent_clk[CLK_EXTAL] = ext->ext_clk_rate;
+ module_ctx.parent_clk[CLK_OSC_EXTAL] = r8a7795_cpg_init(ext->ext_clk_rate);
+ module_ctx.parent_clk[CLK_PLL1] = r8a7795_cpg_pll1_init(ext->ext_clk_rate);
+ module_ctx.parent_clk[CLK_PLL1_DIV2] = module_ctx.parent_clk[CLK_PLL1] / 2;
+ module_ctx.parent_clk[CLK_PLL1_DIV4] = module_ctx.parent_clk[CLK_PLL1] / 4;
+ ;
+ module_ctx.parent_clk[CLK_S0] = module_ctx.parent_clk[CLK_PLL1_DIV2] / 2;
+ module_ctx.parent_clk[CLK_S1] = module_ctx.parent_clk[CLK_PLL1_DIV2] / 3;
+ module_ctx.parent_clk[CLK_S2] = module_ctx.parent_clk[CLK_PLL1_DIV2] / 4;
+ module_ctx.parent_clk[CLK_S3] = module_ctx.parent_clk[CLK_PLL1_DIV2] / 6;
+ module_ctx.parent_clk[CLK_SDSRC] = module_ctx.parent_clk[CLK_PLL1_DIV2] / 2;
+
+ return FWK_SUCCESS;
+}
+
+static int sd_clock_element_init(
+ fwk_id_t element_id,
+ unsigned int sub_element_count,
+ const void *data)
+{
+ struct rcar_sd_clock_dev_ctx *ctx;
+ const struct mod_rcar_sd_clock_dev_config *dev_config = data;
+ unsigned int i = 0;
+ uint64_t current_rate;
+ uint64_t last_rate = 0;
+
+ if (!fwk_module_is_valid_element_id(element_id))
+ return FWK_E_PARAM;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id);
+ ctx->config = dev_config;
+
+ if (ctx->config->rate_count > 0) {
+ ctx->rate_table =
+ fwk_mm_calloc(ctx->config->rate_count, sizeof(uint64_t));
+ if (ctx->rate_table == NULL)
+ return FWK_E_NOMEM;
+
+ for (i = 0; i < ctx->config->rate_count; i++)
+ ctx->rate_table[i] = module_ctx.parent_clk[ctx->config->parent] /
+ ctx->config->rate_table[i].divider_num;
+ }
+
+ /* Verify that the rate entries in the device's lookup table are ordered */
+ if (dev_config->rate_type == MOD_CLOCK_RATE_TYPE_CONTINUOUS) {
+ if (ctx->rate_table[0] > ctx->rate_table[1])
+ return FWK_E_DATA;
+ } else {
+ i = 0;
+ while (i < dev_config->rate_count) {
+ current_rate = ctx->rate_table[i];
+
+ /* The rate entries must be in ascending order */
+ if (current_rate < last_rate)
+ return FWK_E_DATA;
+
+ last_rate = current_rate;
+ i++;
+ }
+ }
+
+ ctx->initialized = true;
+
+ return FWK_SUCCESS;
+}
+
+static int sd_clock_process_bind_request(
+ fwk_id_t source_id,
+ fwk_id_t target_id,
+ fwk_id_t api_id,
+ const void **api)
+{
+ *api = &api_clock;
+ return FWK_SUCCESS;
+}
+
+static int sd_clock_start(fwk_id_t id)
+{
+ int ret = FWK_SUCCESS;
+ ret = sd_clock_resume();
+ return ret;
+}
+
+const struct fwk_module module_rcar_sd_clock = {
+ .name = "SD Clock Driver",
+ .type = FWK_MODULE_TYPE_DRIVER,
+ .api_count = MOD_RCAR_CLOCK_API_COUNT,
+ .event_count = 0,
+ .init = sd_clock_init,
+ .element_init = sd_clock_element_init,
+ .process_bind_request = sd_clock_process_bind_request,
+ .start = sd_clock_start,
+};
diff --git a/product/rcar/scp_ramfw/config_rcar_sd_clock.c b/product/rcar/scp_ramfw/config_rcar_sd_clock.c
new file mode 100644
index 00000000..56639165
--- /dev/null
+++ b/product/rcar/scp_ramfw/config_rcar_sd_clock.c
@@ -0,0 +1,658 @@
+/*
+ * Renesas SCP/MCP Software
+ * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <clock_sd_devices.h>
+#include <system_clock.h>
+
+#include <mod_rcar_clock.h>
+#include <mod_rcar_sd_clock.h>
+
+#include <fwk_element.h>
+#include <fwk_id.h>
+#include <fwk_macros.h>
+#include <fwk_module.h>
+
+/*
+ * Rate lookup tables
+ */
+static const struct mod_rcar_sd_clock_rate rate_table_sys_ztr[] = {
+ {
+ /* 1/24 */
+ .divider_num = 24,
+ .divider = CPG_FRQCRB_ZTRFC_24,
+ .divider_mask = CPG_FRQCRB_ZTRFC_MASK,
+ },
+ {
+ /* 1/18 */
+ .divider_num = 18,
+ .divider = CPG_FRQCRB_ZTRFC_18,
+ .divider_mask = CPG_FRQCRB_ZTRFC_MASK,
+ },
+ {
+ /* 1/16 */
+ .divider_num = 16,
+ .divider = CPG_FRQCRB_ZTRFC_16,
+ .divider_mask = CPG_FRQCRB_ZTRFC_MASK,
+ },
+ {
+ /* 1/12 */
+ .divider_num = 12,
+ .divider = CPG_FRQCRB_ZTRFC_12,
+ .divider_mask = CPG_FRQCRB_ZTRFC_MASK,
+ },
+ {
+ /* 1/8 */
+ .divider_num = 8,
+ .divider = CPG_FRQCRB_ZTRFC_8,
+ .divider_mask = CPG_FRQCRB_ZTRFC_MASK,
+ },
+ {
+ /* 1/6 */
+ .divider_num = 6,
+ .divider = CPG_FRQCRB_ZTRFC_6,
+ .divider_mask = CPG_FRQCRB_ZTRFC_MASK,
+ },
+};
+
+static const struct mod_rcar_sd_clock_rate rate_table_sys_ztrd2[] = {
+ {
+ /* 1/24 */
+ .divider_num = 24,
+ .divider = CPG_FRQCRB_ZTRD2FC_24,
+ .divider_mask = CPG_FRQCRB_ZTRD2FC_MASK,
+ },
+ {
+ /* 1/18 */
+ .divider_num = 18,
+ .divider = CPG_FRQCRB_ZTRD2FC_18,
+ .divider_mask = CPG_FRQCRB_ZTRD2FC_MASK,
+ },
+ {
+ /* 1/16 */
+ .divider_num = 16,
+ .divider = CPG_FRQCRB_ZTRD2FC_16,
+ .divider_mask = CPG_FRQCRB_ZTRD2FC_MASK,
+ },
+ {
+ /* 1/12 */
+ .divider_num = 12,
+ .divider = CPG_FRQCRB_ZTRD2FC_12,
+ .divider_mask = CPG_FRQCRB_ZTRD2FC_MASK,
+ },
+};
+
+static const struct mod_rcar_sd_clock_rate rate_table_sys_zt[] = {
+ {
+ /* 1/24 */
+ .divider_num = 24,
+ .divider = CPG_FRQCRB_ZTFC_24,
+ .divider_mask = CPG_FRQCRB_ZTFC_MASK,
+ },
+ {
+ /* 1/18 */
+ .divider_num = 18,
+ .divider = CPG_FRQCRB_ZTFC_18,
+ .divider_mask = CPG_FRQCRB_ZTFC_MASK,
+ },
+ {
+ /* 1/16 */
+ .divider_num = 16,
+ .divider = CPG_FRQCRB_ZTFC_16,
+ .divider_mask = CPG_FRQCRB_ZTFC_MASK,
+ },
+ {
+ /* 1/12 */
+ .divider_num = 12,
+ .divider = CPG_FRQCRB_ZTFC_12,
+ .divider_mask = CPG_FRQCRB_ZTFC_MASK,
+ },
+ {
+ /* 1/8 */
+ .divider_num = 8,
+ .divider = CPG_FRQCRB_ZTFC_8,
+ .divider_mask = CPG_FRQCRB_ZTFC_MASK,
+ },
+ {
+ /* 1/6 */
+ .divider_num = 6,
+ .divider = CPG_FRQCRB_ZTFC_6,
+ .divider_mask = CPG_FRQCRB_ZTFC_MASK,
+ },
+ {
+ /* 1/4 */
+ .divider_num = 4,
+ .divider = CPG_FRQCRB_ZTFC_4,
+ .divider_mask = CPG_FRQCRB_ZTFC_MASK,
+ },
+};
+
+static const struct mod_rcar_sd_clock_rate rate_table_sys_sd[] = {
+ {
+ /* 1/64 */
+ .divider_num = 64,
+ .divider = CPG_SDNCKCR_SD_64,
+ .divider_mask = CPG_SDNCKCR_MASK,
+ },
+ {
+ /* 1/32 */
+ .divider_num = 32,
+ .divider = CPG_SDNCKCR_SD_32,
+ .divider_mask = CPG_SDNCKCR_MASK,
+ },
+ {
+ /* 1/16 */
+ .divider_num = 16,
+ .divider = CPG_SDNCKCR_SD_16,
+ .divider_mask = CPG_SDNCKCR_MASK,
+ },
+ {
+ /* 1/8 */
+ .divider_num = 8,
+ .divider = CPG_SDNCKCR_SD_8,
+ .divider_mask = CPG_SDNCKCR_MASK,
+ },
+ {
+ /* 1/4 */
+ .divider_num = 4,
+ .divider = CPG_SDNCKCR_SD_4,
+ .divider_mask = CPG_SDNCKCR_MASK,
+ },
+ {
+ /* 1/2 */
+ .divider_num = 2,
+ .divider = CPG_SDNCKCR_SD_2,
+ .divider_mask = CPG_SDNCKCR_MASK,
+ },
+};
+
+static const struct mod_rcar_sd_clock_rate rate_table_sys_ckcr[] = {
+ /* min rate*/
+ {
+ .divider_num = 64,
+ },
+ /* max rate*/
+ {
+ .divider_num = 1,
+ },
+ /* step rate*/
+ {
+ .divider_num = 64,
+ },
+};
+
+static const struct fwk_element pik_clock_element_table[] = {
+ {
+ .name = "ztr",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_FRQCRB,
+ .stop_clk = false,
+ .parent = CLK_PLL1_DIV2,
+ .div = 6,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ .rate_table = rate_table_sys_ztr,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_ztr),
+ }),
+ },
+ {
+ .name = "ztrd2",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_FRQCRB,
+ .stop_clk = false,
+ .parent = CLK_PLL1_DIV2,
+ .div = 12,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ .rate_table = rate_table_sys_ztrd2,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_ztrd2),
+ }),
+ },
+ {
+ .name = "zt",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_FRQCRB,
+ .stop_clk = false,
+ .parent = CLK_PLL1_DIV2,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ .rate_table = rate_table_sys_zt,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_zt),
+ }),
+ },
+ {
+ .name = "zx",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .control_reg = CPG_FRQCRB,
+ .parent = CLK_PLL1_DIV2,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s0d1",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S0,
+ .div = 1,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s0d2",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S0,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s0d3",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S0,
+ .div = 3,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s0d4",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S0,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s0d6",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S0,
+ .div = 6,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s0d8",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S0,
+ .div = 8,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s0d12",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S0,
+ .div = 12,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s1d1",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S1,
+ .div = 1,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s1d2",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S1,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s1d4",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S1,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s2d1",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S2,
+ .div = 1,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s2d2",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S2,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s2d4",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S2,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s3d1",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S3,
+ .div = 1,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s3d2",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S3,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s3d4",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_S3,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "sd0",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_SD0CKCR,
+ .stop_clk = true,
+ .stop_clk_bit = 8,
+ .parent = CLK_SDSRC,
+ .need_hardware_init = true,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ .rate_table = rate_table_sys_sd,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_sd),
+ }),
+ },
+ {
+ .name = "sd1",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_SD1CKCR,
+ .stop_clk = true,
+ .stop_clk_bit = 8,
+ .parent = CLK_SDSRC,
+ .need_hardware_init = true,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ .rate_table = rate_table_sys_sd,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_sd),
+ }),
+ },
+ {
+ .name = "sd2",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_SD2CKCR,
+ .stop_clk = true,
+ .stop_clk_bit = 8,
+ .parent = CLK_SDSRC,
+ .need_hardware_init = true,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ .rate_table = rate_table_sys_sd,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_sd),
+ }),
+ },
+ {
+ .name = "sd3",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_SD3CKCR,
+ .stop_clk = true,
+ .stop_clk_bit = 8,
+ .parent = CLK_SDSRC,
+ .need_hardware_init = true,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ .rate_table = rate_table_sys_sd,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_sd),
+ }),
+ },
+ {
+ .name = "cl",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_PLL1_DIV2,
+ .div = 48,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "cr",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_PLL1_DIV4,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "cp",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_EXTAL,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "cpex",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_EXTAL,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "canfd",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_CANFDCKCR,
+ .stop_clk = true,
+ .stop_clk_bit = 8,
+ .parent = CLK_PLL1_DIV4,
+ .div = 64,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_CONTINUOUS,
+ .rate_table = rate_table_sys_ckcr,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_ckcr),
+ }),
+ },
+ {
+ .name = "csi0",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_CSI0CKCR,
+ .stop_clk = true,
+ .stop_clk_bit = 8,
+ .parent = CLK_PLL1_DIV4,
+ .div = 64,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_CONTINUOUS,
+ .rate_table = rate_table_sys_ckcr,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_ckcr),
+ }),
+ },
+ {
+ .name = "mso",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_MSOCKCR,
+ .stop_clk = true,
+ .stop_clk_bit = 8,
+ .parent = CLK_PLL1_DIV4,
+ .div = 63,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_CONTINUOUS,
+ .rate_table = rate_table_sys_ckcr,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_ckcr),
+ }),
+ },
+ {
+ .name = "hdmi",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
+ .control_reg = CPG_HDMICKCR,
+ .stop_clk = true,
+ .stop_clk_bit = 8,
+ .parent = CLK_PLL1_DIV4,
+ .div = 63,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_CONTINUOUS,
+ .rate_table = rate_table_sys_ckcr,
+ .rate_count = FWK_ARRAY_SIZE(rate_table_sys_ckcr),
+ }),
+ },
+ {
+ .name = "osc",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_OSC_EXTAL,
+ .div = 8,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "r",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_OSC_EXTAL,
+ .div = 32,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s0",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_PLL1_DIV2,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s1",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_PLL1_DIV2,
+ .div = 3,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s2",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_PLL1_DIV2,
+ .div = 4,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "s3",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_PLL1_DIV2,
+ .div = 6,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "sdsrc",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_PLL1_DIV2,
+ .div = 2,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ {
+ .name = "rint",
+ .data = &((struct mod_rcar_sd_clock_dev_config){
+ .type = MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
+ .parent = CLK_OSC_EXTAL,
+ .div = 32,
+ .multi = 1,
+ .rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE,
+ }),
+ },
+ { 0 }, /* Termination description. */
+};
+
+static const struct fwk_element *pik_clock_get_element_table(fwk_id_t module_id)
+{
+ return pik_clock_element_table;
+}
+
+struct fwk_module_config config_rcar_sd_clock = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(pik_clock_get_element_table),
+ .data = &((struct mod_ext_clock_rate){
+ .ext_clk_rate = PLL_BASE_CLOCK,
+ }),
+};