From 0bc640fd693982bbadee44e6a0d50c95596f4dd1 Mon Sep 17 00:00:00 2001 From: Nicolas Royer Date: Sun, 27 Sep 2020 17:39:40 +0200 Subject: rcar/module: add rcar mstp_clock module and config data Change-Id: I979fecb8b71fb7a1f962574d8bc6f439e7bfb68d Signed-off-by: Tsutomu Muroya Signed-off-by: Nicolas Royer --- .../rcar_mstp_clock/include/mod_rcar_mstp_clock.h | 104 ++++++++++ product/rcar/module/rcar_mstp_clock/src/Makefile | 11 ++ .../rcar_mstp_clock/src/mod_rcar_mstp_clock.c | 210 +++++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 product/rcar/module/rcar_mstp_clock/include/mod_rcar_mstp_clock.h create mode 100644 product/rcar/module/rcar_mstp_clock/src/Makefile create mode 100644 product/rcar/module/rcar_mstp_clock/src/mod_rcar_mstp_clock.c (limited to 'product/rcar/module') diff --git a/product/rcar/module/rcar_mstp_clock/include/mod_rcar_mstp_clock.h b/product/rcar/module/rcar_mstp_clock/include/mod_rcar_mstp_clock.h new file mode 100644 index 00000000..099e5e26 --- /dev/null +++ b/product/rcar/module/rcar_mstp_clock/include/mod_rcar_mstp_clock.h @@ -0,0 +1,104 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_RCAR_MSTP_CLOCK_H +#define MOD_RCAR_MSTP_CLOCK_H + +#include + +#include +#include + +#include + +#include + +/*! + * \addtogroup GroupRCARModule RCAR Product Modules + * @{ + */ + +/*! + * \defgroup GroupRCARMstpClock MSTP Clock + * @{ + */ + +/*! + * \brief Subsystem clock device configuration. + */ +struct mod_rcar_mstp_clock_dev_config { + /*! Pointer to the clock's control register. */ + volatile uint32_t const control_reg; + + /*! enable / disable bit position. */ + volatile uint32_t const bit; + + /*! If true, the driver will provide a default clock supply. */ + const bool defer_initialization; +}; + +/*! + * @cond + */ + +/* Device context */ +struct rcar_mstp_clock_dev_ctx { + bool initialized; + uint64_t current_rate; + enum mod_clock_state current_state; + const struct mod_rcar_mstp_clock_dev_config *config; + struct mod_rcar_clock_drv_api *api; +}; + +struct mod_rcar_mstp_clock_init { + volatile uint32_t const smstpcr_init[12]; +}; + +/* Module context */ +struct rcar_mstp_clock_ctx { + struct rcar_mstp_clock_dev_ctx *dev_ctx_table; + unsigned int dev_count; + const struct mod_rcar_mstp_clock_init *mstp_init; +}; + +/* Module Stop Status Register offsets */ +static const uint16_t mstpsr[] = { + 0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, + 0x1C0, 0x1C4, 0x9A0, 0x9A4, 0x9A8, 0x9AC, +}; + +/* System Module Stop Control Register offsets */ +static const uint16_t smstpcr[] = { + 0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, + 0x148, 0x14C, 0x990, 0x994, 0x998, 0x99C, +}; + +/* System Module Stop Control Register Number */ +#define CPG_SMSTPCR1 1 +#define CPG_SMSTPCR2 2 +#define CPG_SMSTPCR3 3 +#define CPG_SMSTPCR4 4 +#define CPG_SMSTPCR5 5 +#define CPG_SMSTPCR6 6 +#define CPG_SMSTPCR7 7 +#define CPG_SMSTPCR8 8 +#define CPG_SMSTPCR9 9 +#define CPG_SMSTPCR10 10 + +/*! + * @endcond + */ + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_RCAR_MSTP_CLOCK_H */ diff --git a/product/rcar/module/rcar_mstp_clock/src/Makefile b/product/rcar/module/rcar_mstp_clock/src/Makefile new file mode 100644 index 00000000..fe4acb10 --- /dev/null +++ b/product/rcar/module/rcar_mstp_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_mstp_clock.c + +include $(BS_DIR)/lib.mk diff --git a/product/rcar/module/rcar_mstp_clock/src/mod_rcar_mstp_clock.c b/product/rcar/module/rcar_mstp_clock/src/mod_rcar_mstp_clock.c new file mode 100644 index 00000000..36d3e8b6 --- /dev/null +++ b/product/rcar/module/rcar_mstp_clock/src/mod_rcar_mstp_clock.c @@ -0,0 +1,210 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +static struct rcar_mstp_clock_ctx module_ctx; + +/* + * Static helper functions + */ +static int mstp_clock_set_state( + fwk_id_t dev_id, + enum mod_clock_state target_state) +{ + struct rcar_mstp_clock_dev_ctx *ctx; + uint32_t value; + int i; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + value = mmio_read_32(CPG_BASE + smstpcr[ctx->config->control_reg]); + if (MOD_CLOCK_STATE_RUNNING == target_state) + value &= ~(BIT(ctx->config->bit)); + else + value |= BIT(ctx->config->bit); + + mmio_write_32((CPG_BASE + smstpcr[ctx->config->control_reg]), value); + + if (MOD_CLOCK_STATE_RUNNING == target_state) { + for (i = 1000; i > 0; --i) { + if (!(mmio_read_32(CPG_BASE + mstpsr[ctx->config->control_reg]) & + BIT(ctx->config->bit))) + break; + } + + if (!i) + return FWK_E_TIMEOUT; + } + + ctx->current_state = target_state; + return FWK_SUCCESS; +} + +static int mstp_clock_get_state(fwk_id_t dev_id, enum mod_clock_state *state) +{ + struct rcar_mstp_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 void mstp_clock_hw_initial_set_state( + fwk_id_t element_id, + struct rcar_mstp_clock_dev_ctx *ctx) +{ + /* Maintain clock supply at startup. */ + if (module_ctx.mstp_init->smstpcr_init[ctx->config->control_reg] & + BIT(ctx->config->bit)) + ctx->current_state = MOD_CLOCK_STATE_STOPPED; + else + ctx->current_state = MOD_CLOCK_STATE_RUNNING; + + /* If true, the driver will provide a default clock supply. */ + if (ctx->config->defer_initialization) + mstp_clock_set_state(element_id, MOD_CLOCK_STATE_RUNNING); +} + +static int mstp_clock_resume(void) +{ + fwk_id_t element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLK_ID_MSTP_START); + uint32_t mstp_id; + struct rcar_mstp_clock_dev_ctx *ctx; + + for (mstp_id = CLK_ID_MSTP_START; mstp_id < CLK_ID_MSTP_END; mstp_id++) { + element_id.element.element_idx = mstp_id; + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id); + mstp_clock_hw_initial_set_state(element_id, ctx); + } + return FWK_SUCCESS; +} + +static int mstp_clock_set_rate( + fwk_id_t dev_id, + uint64_t rate, + enum mod_clock_round_mode round_mode) +{ + return FWK_E_PARAM; +} + +static int mstp_clock_get_rate(fwk_id_t dev_id, uint64_t *rate) +{ + return FWK_E_PARAM; +} + +static int mstp_clock_get_rate_from_index( + fwk_id_t dev_id, + unsigned int rate_index, + uint64_t *rate) +{ + return FWK_E_PARAM; +} + +static int mstp_clock_get_range(fwk_id_t dev_id, struct mod_clock_range *range) +{ + return FWK_E_PARAM; +} + +static const struct mod_rcar_clock_drv_api api_clock = { + .set_state = mstp_clock_set_state, + .get_state = mstp_clock_get_state, + .resume = mstp_clock_resume, + .set_rate = mstp_clock_set_rate, + .get_rate = mstp_clock_get_rate, + .get_rate_from_index = mstp_clock_get_rate_from_index, + .get_range = mstp_clock_get_range, +}; + +/* + * Framework handler functions + */ + +static int mstp_clock_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + const struct mod_rcar_mstp_clock_init *mstp_init = data; + + module_ctx.dev_count = element_count; + + if (element_count == 0) + return FWK_SUCCESS; + + if (mstp_init == NULL) + return FWK_E_PARAM; + + module_ctx.mstp_init = mstp_init; + module_ctx.dev_ctx_table = + fwk_mm_calloc(element_count, sizeof(struct rcar_mstp_clock_dev_ctx)); + if (module_ctx.dev_ctx_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int mstp_clock_element_init( + fwk_id_t element_id, + unsigned int sub_element_count, + const void *data) +{ + struct rcar_mstp_clock_dev_ctx *ctx; + const struct mod_rcar_mstp_clock_dev_config *dev_config = data; + + 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; + ctx->initialized = true; + + return FWK_SUCCESS; +} + +static int mstp_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 mstp_clock_start(fwk_id_t id) +{ + int ret = FWK_SUCCESS; + ret = mstp_clock_resume(); + return ret; +} + +const struct fwk_module module_rcar_mstp_clock = { + .name = "MSTP Clock Driver", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = MOD_RCAR_CLOCK_API_COUNT, + .event_count = 0, + .init = mstp_clock_init, + .element_init = mstp_clock_element_init, + .process_bind_request = mstp_clock_process_bind_request, + .start = mstp_clock_start, +}; -- cgit v1.2.3