1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 * JUNO Reset Domain Driver
9 * Arm platforms don't have proper reset domains. However for completeness,
10 * this driver demonstrates reset functionality using Juno UART as an
11 * example reset domain peripheral. Only auto reset functionality is
12 * implemented as explicit assert/de-assert complicates functionality of
13 * UART peripheral.
14 */
15
16 #include <juno_scc.h>
17 #include <system_mmap.h>
18
19 #include <mod_juno_reset_domain.h>
20 #include <mod_reset_domain.h>
21
22 #include <fwk_assert.h>
23 #include <fwk_core.h>
24 #include <fwk_macros.h>
25 #include <fwk_mm.h>
26 #include <fwk_module.h>
27 #include <fwk_module_idx.h>
28 #include <fwk_status.h>
29
30 enum dev_state {
31 DEVICE_STATE_NORMAL = 0,
32 DEVICE_STATE_RESET = 1
33 };
34
35 struct juno_reset_dev_ctx {
36 void *config;
37 bool reset_state;
38 };
39
40 struct juno_reset_domain_module_ctx {
41 const struct mod_reset_domain_drv_input_api *drv_input_api;
42 fwk_id_t reset_domain_hal_id;
43 struct juno_reset_dev_ctx *dev_ctx_table;
44 uint32_t cookie;
45 };
46
47 static struct juno_reset_domain_module_ctx module_juno_reset_ctx;
48
49 /* Helper functions */
handle_uart_reset_set_state(struct juno_reset_dev_ctx * dev_ctx)50 static int handle_uart_reset_set_state(struct juno_reset_dev_ctx *dev_ctx)
51 {
52 int retry = 5;
53 int status = FWK_E_DEVICE;
54
55 struct mod_juno_reset_uart_config* uart_config =
56 (struct mod_juno_reset_uart_config*)dev_ctx->config;
57
58 if (dev_ctx->reset_state == DEVICE_STATE_RESET) {
59 return FWK_E_STATE;
60 }
61
62 /* Reset UART device */
63 dev_ctx->reset_state = DEVICE_STATE_RESET;
64 *uart_config->reset_reg |= uart_config->reset_mask;
65
66 /* Check if reset of the device has been taken place
67 * On juno board unlikely we will see mutliple retries.
68 */
69 while (retry--) {
70 if (*uart_config->reset_reg & uart_config->reset_mask) {
71 /* We are only supporting auto reset and architecture reset
72 * so clear juno UART reset.
73 */
74 *uart_config->reset_reg &= ~uart_config->reset_mask;
75 status = FWK_SUCCESS;
76 dev_ctx->reset_state = DEVICE_STATE_NORMAL;
77 break;
78 }
79 }
80
81 return status;
82 }
83
84 /*
85 * Module APIs
86 */
juno_set_reset_state(fwk_id_t dev_id,enum mod_reset_domain_mode mode,uint32_t reset_state,uintptr_t cookie)87 static int juno_set_reset_state(fwk_id_t dev_id,
88 enum mod_reset_domain_mode mode,
89 uint32_t reset_state,
90 uintptr_t cookie)
91 {
92 int status;
93 struct juno_reset_dev_ctx *dev_ctx;
94 struct mod_reset_domain_autoreset_event_params *params;
95 struct fwk_event autoreset_event = {
96 .id = mod_reset_domain_autoreset_event_id,
97 .target_id = fwk_module_id_reset_domain,
98 };
99 unsigned int domain_idx = fwk_id_get_element_idx(dev_id);
100
101 if (domain_idx >= JUNO_RESET_DOMAIN_IDX_COUNT) {
102 return FWK_E_PARAM;
103 }
104
105 dev_ctx = &module_juno_reset_ctx.dev_ctx_table[domain_idx];
106
107 if (domain_idx == JUNO_RESET_DOMAIN_IDX_UART) {
108 status = handle_uart_reset_set_state(dev_ctx);
109 if (status != FWK_SUCCESS) {
110 return status;
111 }
112
113 params = (struct mod_reset_domain_autoreset_event_params *)
114 autoreset_event.params;
115 params->dev_id = dev_id;
116 params->reset_state = reset_state;
117 params->cookie = cookie;
118 fwk_put_event(&autoreset_event);
119 }
120
121 return FWK_SUCCESS;
122 }
123
124 static struct mod_reset_domain_drv_api juno_reset_domain_drv_api = {
125 .set_reset_state = juno_set_reset_state,
126 };
127
128 /*
129 * Framework handlers
130 */
juno_reset_domain_init(fwk_id_t module_id,unsigned int element_count,const void * data)131 static int juno_reset_domain_init(fwk_id_t module_id,
132 unsigned int element_count,
133 const void *data)
134 {
135 /* This module supports only one reset device
136 */
137 fwk_assert(element_count == 1);
138 module_juno_reset_ctx.dev_ctx_table = fwk_mm_calloc(element_count,
139 sizeof(struct juno_reset_dev_ctx));
140
141 return FWK_SUCCESS;
142 }
143
juno_reset_domain_element_init(fwk_id_t element_id,unsigned int sub_element_count,const void * data)144 static int juno_reset_domain_element_init(fwk_id_t element_id,
145 unsigned int sub_element_count,
146 const void *data)
147 {
148 struct juno_reset_dev_ctx* dev_ctx = NULL;
149
150 dev_ctx = &module_juno_reset_ctx.dev_ctx_table[
151 fwk_id_get_element_idx(element_id)];
152 dev_ctx->config = (void*)data;
153
154 return FWK_SUCCESS;
155 }
156
juno_reset_domain_bind(fwk_id_t id,unsigned int round)157 static int juno_reset_domain_bind(fwk_id_t id, unsigned int round)
158 {
159 return FWK_SUCCESS;
160 }
161
juno_reset_domain_process_bind_request(fwk_id_t source_id,fwk_id_t target_id,fwk_id_t api_id,const void ** api)162 static int juno_reset_domain_process_bind_request(fwk_id_t source_id,
163 fwk_id_t target_id,
164 fwk_id_t api_id,
165 const void **api)
166 {
167 fwk_id_t mod_juno_reset_domain_api_id_driver =
168 FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_RESET_DOMAIN,
169 MOD_JUNO_RESET_DOMAIN_API_IDX_DRIVER);
170
171 if (!fwk_id_is_type(target_id, FWK_ID_TYPE_ELEMENT) ||
172 !fwk_id_is_equal(api_id, mod_juno_reset_domain_api_id_driver) ||
173 api == NULL) {
174 return FWK_E_PARAM;
175 }
176
177 *api = &juno_reset_domain_drv_api;
178
179 module_juno_reset_ctx.reset_domain_hal_id = source_id;
180
181 return FWK_SUCCESS;
182 }
183
juno_reset_domain_start(fwk_id_t id)184 static int juno_reset_domain_start(fwk_id_t id)
185 {
186 return FWK_SUCCESS;
187 }
188
189 struct fwk_module module_juno_reset_domain = {
190 .type = FWK_MODULE_TYPE_DRIVER,
191 .api_count = MOD_JUNO_RESET_DOMAIN_API_IDX_COUNT,
192 .init = juno_reset_domain_init,
193 .element_init = juno_reset_domain_element_init,
194 .bind = juno_reset_domain_bind,
195 .process_bind_request = juno_reset_domain_process_bind_request,
196 .start = juno_reset_domain_start,
197 };
198