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