1 /*
2  * Renesas SCP/MCP Software
3  * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights
4  * reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include <mod_reset_domain.h>
10 #include <mod_rcar_reset.h>
11 #include <mmio.h>
12 
13 #include <fwk_assert.h>
14 #include <fwk_element.h>
15 #include <fwk_status.h>
16 #include <fwk_mm.h>
17 #include <fwk_module.h>
18 #include <fwk_module_idx.h>
19 
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <lib/utils_def.h>
23 
24 static struct rcar_reset_ctx module_ctx;
25 
26 /*
27  * Static helper functions
28  */
udelay(uint32_t cycles)29 static void udelay(uint32_t cycles)
30 {
31   volatile uint32_t i;
32 
33     for (i = 0UL; i < cycles ; ++i)
34         __asm__ volatile ("nop");
35 }
36 
rcar_auto_domain(fwk_id_t dev_id,uint32_t state)37 static int rcar_auto_domain(fwk_id_t dev_id, uint32_t state)
38 {
39     struct rcar_reset_dev_ctx *ctx;
40 
41     ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
42 
43     mmio_write_32((CPG_BASE + srcr[ctx->config->control_reg]),
44                    BIT(ctx->config->bit));
45 
46     /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
47     udelay(SCSR_DELAY_US);
48 
49     /* Release module from reset state */
50     mmio_write_32((CPG_BASE + SRSTCLR(ctx->config->control_reg)),
51                    BIT(ctx->config->bit));
52 
53     return FWK_SUCCESS;
54 }
55 
rcar_assert_domain(fwk_id_t dev_id)56 static int rcar_assert_domain(fwk_id_t dev_id)
57 {
58     struct rcar_reset_dev_ctx *ctx;
59 
60     ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
61 
62     mmio_write_32((CPG_BASE + srcr[ctx->config->control_reg]),
63                    BIT(ctx->config->bit));
64 
65     return FWK_SUCCESS;
66 }
67 
rcar_deassert_domain(fwk_id_t dev_id)68 static int rcar_deassert_domain(fwk_id_t dev_id)
69 {
70     struct rcar_reset_dev_ctx *ctx;
71 
72     ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
73 
74     mmio_write_32((CPG_BASE + SRSTCLR(ctx->config->control_reg)),
75                    BIT(ctx->config->bit));
76 
77     return FWK_SUCCESS;
78 }
79 
rcar_set_reset_state(fwk_id_t dev_id,enum mod_reset_domain_mode mode,uint32_t reset_state,uintptr_t cookie)80 static int rcar_set_reset_state(fwk_id_t dev_id,
81                            enum mod_reset_domain_mode mode,
82                            uint32_t reset_state,
83                            uintptr_t cookie)
84 {
85 
86     switch (mode) {
87     case MOD_RESET_DOMAIN_AUTO_RESET:
88         rcar_auto_domain(dev_id, reset_state);
89         break;
90 
91     case MOD_RESET_DOMAIN_MODE_EXPLICIT_ASSERT:
92         rcar_assert_domain(dev_id);
93         break;
94 
95     case MOD_RESET_DOMAIN_MODE_EXPLICIT_DEASSERT:
96         rcar_deassert_domain(dev_id);
97         break;
98 
99     default:
100         return FWK_E_ACCESS;
101     }
102 
103     return FWK_SUCCESS;
104 }
105 
106 static const struct mod_reset_domain_drv_api api_reset = {
107     .set_reset_state = rcar_set_reset_state,
108 };
109 
110 /*
111  * Framework handler functions
112  */
113 
reset_init(fwk_id_t module_id,unsigned int element_count,const void * data)114 static int reset_init(fwk_id_t module_id, unsigned int element_count,
115                           const void *data)
116 {
117     module_ctx.dev_count = element_count;
118 
119     if (element_count == 0)
120         return FWK_SUCCESS;
121 
122     module_ctx.dev_ctx_table = fwk_mm_calloc(element_count,
123                                          sizeof(struct rcar_reset_dev_ctx));
124     if (module_ctx.dev_ctx_table == NULL)
125         return FWK_E_NOMEM;
126 
127     return FWK_SUCCESS;
128 }
129 
reset_element_init(fwk_id_t element_id,unsigned int sub_element_count,const void * data)130 static int reset_element_init(fwk_id_t element_id,
131                                   unsigned int sub_element_count,
132                                   const void *data)
133 {
134     struct rcar_reset_dev_ctx *ctx;
135     const struct mod_rcar_reset_dev_config *dev_config = data;
136 
137     if (!fwk_module_is_valid_element_id(element_id))
138         return FWK_E_PARAM;
139 
140     ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id);
141     ctx->config = dev_config;
142 
143     return FWK_SUCCESS;
144 }
145 
reet_process_bind_request(fwk_id_t source_id,fwk_id_t target_id,fwk_id_t api_id,const void ** api)146 static int reet_process_bind_request(fwk_id_t source_id,
147                                           fwk_id_t target_id, fwk_id_t api_id,
148                                           const void **api)
149 {
150     *api = &api_reset;
151     return FWK_SUCCESS;
152 }
153 
154 const struct fwk_module module_rcar_reset = {
155     .type = FWK_MODULE_TYPE_DRIVER,
156     .api_count = MOD_RCAR_RESET_API_COUNT,
157     .event_count = 0,
158     .init = reset_init,
159     .element_init = reset_element_init,
160     .process_bind_request = reet_process_bind_request,
161 };
162