1 /* 2 * Copyright (c) 2020-2022, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <stdbool.h> 9 #include <stdint.h> 10 11 #include "mhu_v2_x.h" 12 13 #define MHU_V2_X_MAX_CHANNELS 124 14 #define MHU_V2_1_MAX_CHCOMB_INT 4 15 #define ENABLE 0x1 16 #define DISABLE 0x0 17 #define CLEAR_INTR 0x1 18 #define CH_PER_CH_COMB 0x20 19 #define SEND_FRAME(p_mhu) ((struct mhu_v2_x_send_frame_t *)p_mhu) 20 #define RECV_FRAME(p_mhu) ((struct mhu_v2_x_recv_frame_t *)p_mhu) 21 22 #define MHU_MAJOR_REV_V2 0x1u 23 #define MHU_MINOR_REV_2_0 0x0u 24 #define MHU_MINOR_REV_2_1 0x1u 25 26 struct mhu_v2_x_send_ch_window_t { 27 /* Offset: 0x00 (R/ ) Channel Status */ 28 volatile uint32_t ch_st; 29 /* Offset: 0x04 (R/ ) Reserved */ 30 volatile uint32_t reserved_0; 31 /* Offset: 0x08 (R/ ) Reserved */ 32 volatile uint32_t reserved_1; 33 /* Offset: 0x0C ( /W) Channel Set */ 34 volatile uint32_t ch_set; 35 /* Offset: 0x10 (R/ ) Channel Interrupt Status (Reserved in 2.0) */ 36 volatile uint32_t ch_int_st; 37 /* Offset: 0x14 ( /W) Channel Interrupt Clear (Reserved in 2.0) */ 38 volatile uint32_t ch_int_clr; 39 /* Offset: 0x18 (R/W) Channel Interrupt Enable (Reserved in 2.0) */ 40 volatile uint32_t ch_int_en; 41 /* Offset: 0x1C (R/ ) Reserved */ 42 volatile uint32_t reserved_2; 43 }; 44 45 struct mhu_v2_x_send_frame_t { 46 /* Offset: 0x000 ( / ) Sender Channel Window 0 -123 */ 47 struct mhu_v2_x_send_ch_window_t send_ch_window[MHU_V2_X_MAX_CHANNELS]; 48 /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */ 49 volatile uint32_t mhu_cfg; 50 /* Offset: 0xF84 (R/W) Response Configuration */ 51 volatile uint32_t resp_cfg; 52 /* Offset: 0xF88 (R/W) Access Request */ 53 volatile uint32_t access_request; 54 /* Offset: 0xF8C (R/ ) Access Ready */ 55 volatile uint32_t access_ready; 56 /* Offset: 0xF90 (R/ ) Interrupt Status */ 57 volatile uint32_t int_st; 58 /* Offset: 0xF94 ( /W) Interrupt Clear */ 59 volatile uint32_t int_clr; 60 /* Offset: 0xF98 (R/W) Interrupt Enable */ 61 volatile uint32_t int_en; 62 /* Offset: 0xF9C (R/ ) Reserved */ 63 volatile uint32_t reserved_0; 64 /* Offset: 0xFA0 (R/W) Channel Combined IRQ Stat (Reserved in 2.0) */ 65 volatile uint32_t ch_comb_int_st[MHU_V2_1_MAX_CHCOMB_INT]; 66 /* Offset: 0xFC4 (R/ ) Reserved */ 67 volatile uint32_t reserved_1[6]; 68 /* Offset: 0xFC8 (R/ ) Implementer Identification Register */ 69 volatile uint32_t iidr; 70 /* Offset: 0xFCC (R/ ) Architecture Identification Register */ 71 volatile uint32_t aidr; 72 /* Offset: 0xFD0 (R/ ) */ 73 volatile uint32_t pid_1[4]; 74 /* Offset: 0xFE0 (R/ ) */ 75 volatile uint32_t pid_0[4]; 76 /* Offset: 0xFF0 (R/ ) */ 77 volatile uint32_t cid[4]; 78 }; 79 80 struct mhu_v2_x_rec_ch_window_t { 81 /* Offset: 0x00 (R/ ) Channel Status */ 82 volatile uint32_t ch_st; 83 /* Offset: 0x04 (R/ ) Channel Status Masked */ 84 volatile uint32_t ch_st_msk; 85 /* Offset: 0x08 ( /W) Channel Clear */ 86 volatile uint32_t ch_clr; 87 /* Offset: 0x0C (R/ ) Reserved */ 88 volatile uint32_t reserved_0; 89 /* Offset: 0x10 (R/ ) Channel Mask Status */ 90 volatile uint32_t ch_msk_st; 91 /* Offset: 0x14 ( /W) Channel Mask Set */ 92 volatile uint32_t ch_msk_set; 93 /* Offset: 0x18 ( /W) Channel Mask Clear */ 94 volatile uint32_t ch_msk_clr; 95 /* Offset: 0x1C (R/ ) Reserved */ 96 volatile uint32_t reserved_1; 97 }; 98 99 struct mhu_v2_x_recv_frame_t { 100 /* Offset: 0x000 ( / ) Receiver Channel Window 0 -123 */ 101 struct mhu_v2_x_rec_ch_window_t rec_ch_window[MHU_V2_X_MAX_CHANNELS]; 102 /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */ 103 volatile uint32_t mhu_cfg; 104 /* Offset: 0xF84 (R/ ) Reserved */ 105 volatile uint32_t reserved_0[3]; 106 /* Offset: 0xF90 (R/ ) Interrupt Status (Reserved in 2.0) */ 107 volatile uint32_t int_st; 108 /* Offset: 0xF94 (R/ ) Interrupt Clear (Reserved in 2.0) */ 109 volatile uint32_t int_clr; 110 /* Offset: 0xF98 (R/W) Interrupt Enable (Reserved in 2.0) */ 111 volatile uint32_t int_en; 112 /* Offset: 0xF9C (R/ ) Reserved */ 113 volatile uint32_t reserved_1; 114 /* Offset: 0xFA0 (R/ ) Channel Combined IRQ Stat (Reserved in 2.0) */ 115 volatile uint32_t ch_comb_int_st[MHU_V2_1_MAX_CHCOMB_INT]; 116 /* Offset: 0xFB0 (R/ ) Reserved */ 117 volatile uint32_t reserved_2[6]; 118 /* Offset: 0xFC8 (R/ ) Implementer Identification Register */ 119 volatile uint32_t iidr; 120 /* Offset: 0xFCC (R/ ) Architecture Identification Register */ 121 volatile uint32_t aidr; 122 /* Offset: 0xFD0 (R/ ) */ 123 volatile uint32_t pid_1[4]; 124 /* Offset: 0xFE0 (R/ ) */ 125 volatile uint32_t pid_0[4]; 126 /* Offset: 0xFF0 (R/ ) */ 127 volatile uint32_t cid[4]; 128 }; 129 130 union mhu_v2_x_frame { 131 struct mhu_v2_x_send_frame_t send_frame; 132 struct mhu_v2_x_recv_frame_t recv_frame; 133 }; 134 135 enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev, 136 enum mhu_v2_x_supported_revisions rev) 137 { 138 uint32_t AIDR = 0; 139 union mhu_v2_x_frame *p_mhu; 140 141 assert(dev != NULL); 142 143 p_mhu = (union mhu_v2_x_frame *)dev->base; 144 145 if (dev->is_initialized) { 146 return MHU_V_2_X_ERR_ALREADY_INIT; 147 } 148 149 if (rev == MHU_REV_READ_FROM_HW) { 150 /* Read revision from HW */ 151 if (dev->frame == MHU_V2_X_RECEIVER_FRAME) { 152 AIDR = p_mhu->recv_frame.aidr; 153 } else { 154 AIDR = p_mhu->send_frame.aidr; 155 } 156 157 /* Get bits 7:4 to read major revision */ 158 if (((AIDR >> 4) & 0b1111) != MHU_MAJOR_REV_V2) { 159 /* Unsupported MHU version */ 160 return MHU_V_2_X_ERR_UNSUPPORTED_VERSION; 161 } /* No need to save major version, driver only supports MHUv2 */ 162 163 /* Get bits 3:0 to read minor revision */ 164 dev->subversion = AIDR & 0b1111; 165 166 if (dev->subversion != MHU_MINOR_REV_2_0 && 167 dev->subversion != MHU_MINOR_REV_2_1) { 168 /* Unsupported subversion */ 169 return MHU_V_2_X_ERR_UNSUPPORTED_VERSION; 170 } 171 } else { 172 /* Revisions were provided by caller */ 173 if (rev == MHU_REV_2_0) { 174 dev->subversion = MHU_MINOR_REV_2_0; 175 } else if (rev == MHU_REV_2_1) { 176 dev->subversion = MHU_MINOR_REV_2_1; 177 } else { 178 /* Unsupported subversion */ 179 return MHU_V_2_X_ERR_UNSUPPORTED_VERSION; 180 } /* No need to save major version, driver only supports MHUv2 */ 181 } 182 183 dev->is_initialized = true; 184 185 return MHU_V_2_X_ERR_NONE; 186 } 187 188 uint32_t mhu_v2_x_get_num_channel_implemented(const struct mhu_v2_x_dev_t *dev) 189 { 190 union mhu_v2_x_frame *p_mhu; 191 192 assert(dev != NULL); 193 194 p_mhu = (union mhu_v2_x_frame *)dev->base; 195 196 if (!(dev->is_initialized)) { 197 return MHU_V_2_X_ERR_NOT_INIT; 198 } 199 200 if (dev->frame == MHU_V2_X_SENDER_FRAME) { 201 return (SEND_FRAME(p_mhu))->mhu_cfg; 202 } else { 203 assert(dev->frame == MHU_V2_X_RECEIVER_FRAME); 204 return (RECV_FRAME(p_mhu))->mhu_cfg; 205 } 206 } 207 208 enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev, 209 uint32_t channel, uint32_t val) 210 { 211 union mhu_v2_x_frame *p_mhu; 212 213 assert(dev != NULL); 214 215 p_mhu = (union mhu_v2_x_frame *)dev->base; 216 217 if (!(dev->is_initialized)) { 218 return MHU_V_2_X_ERR_NOT_INIT; 219 } 220 221 if (dev->frame == MHU_V2_X_SENDER_FRAME) { 222 (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_set = val; 223 return MHU_V_2_X_ERR_NONE; 224 } else { 225 return MHU_V_2_X_ERR_INVALID_ARG; 226 } 227 } 228 229 enum mhu_v2_x_error_t mhu_v2_x_channel_poll(const struct mhu_v2_x_dev_t *dev, 230 uint32_t channel, uint32_t *value) 231 { 232 union mhu_v2_x_frame *p_mhu; 233 234 assert(dev != NULL); 235 236 p_mhu = (union mhu_v2_x_frame *)dev->base; 237 238 if (!(dev->is_initialized)) { 239 return MHU_V_2_X_ERR_NOT_INIT; 240 } 241 242 if (dev->frame == MHU_V2_X_SENDER_FRAME) { 243 *value = (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_st; 244 return MHU_V_2_X_ERR_NONE; 245 } else { 246 return MHU_V_2_X_ERR_INVALID_ARG; 247 } 248 } 249 250 enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev, 251 uint32_t channel) 252 { 253 union mhu_v2_x_frame *p_mhu; 254 255 assert(dev != NULL); 256 257 p_mhu = (union mhu_v2_x_frame *)dev->base; 258 259 if (!(dev->is_initialized)) { 260 return MHU_V_2_X_ERR_NOT_INIT; 261 } 262 263 if (dev->frame == MHU_V2_X_RECEIVER_FRAME) { 264 (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_clr = UINT32_MAX; 265 return MHU_V_2_X_ERR_NONE; 266 } else { 267 return MHU_V_2_X_ERR_INVALID_ARG; 268 } 269 } 270 271 enum mhu_v2_x_error_t mhu_v2_x_channel_receive( 272 const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value) 273 { 274 union mhu_v2_x_frame *p_mhu; 275 276 assert(dev != NULL); 277 278 p_mhu = (union mhu_v2_x_frame *)dev->base; 279 280 if (!(dev->is_initialized)) { 281 return MHU_V_2_X_ERR_NOT_INIT; 282 } 283 284 if (dev->frame == MHU_V2_X_RECEIVER_FRAME) { 285 *value = (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_st; 286 return MHU_V_2_X_ERR_NONE; 287 } else { 288 return MHU_V_2_X_ERR_INVALID_ARG; 289 } 290 } 291 292 enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set( 293 const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask) 294 { 295 union mhu_v2_x_frame *p_mhu; 296 297 assert(dev != NULL); 298 299 p_mhu = (union mhu_v2_x_frame *)dev->base; 300 301 if (!(dev->is_initialized)) { 302 return MHU_V_2_X_ERR_NOT_INIT; 303 } 304 305 if (dev->frame == MHU_V2_X_RECEIVER_FRAME) { 306 (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_set = mask; 307 return MHU_V_2_X_ERR_NONE; 308 } else { 309 return MHU_V_2_X_ERR_INVALID_ARG; 310 } 311 } 312 313 enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear( 314 const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask) 315 { 316 union mhu_v2_x_frame *p_mhu; 317 318 assert(dev != NULL); 319 320 p_mhu = (union mhu_v2_x_frame *)dev->base; 321 322 if (!(dev->is_initialized)) { 323 return MHU_V_2_X_ERR_NOT_INIT; 324 } 325 326 if (dev->frame == MHU_V2_X_RECEIVER_FRAME) { 327 (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_clr = mask; 328 return MHU_V_2_X_ERR_NONE; 329 } else { 330 return MHU_V_2_X_ERR_INVALID_ARG; 331 } 332 } 333 enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer( 334 const struct mhu_v2_x_dev_t *dev) 335 { 336 union mhu_v2_x_frame *p_mhu; 337 338 assert(dev != NULL); 339 340 p_mhu = (union mhu_v2_x_frame *)dev->base; 341 342 if (!(dev->is_initialized)) { 343 return MHU_V_2_X_ERR_NOT_INIT; 344 } 345 346 if (dev->frame != MHU_V2_X_SENDER_FRAME) { 347 return MHU_V_2_X_ERR_INVALID_ARG; 348 } 349 350 (SEND_FRAME(p_mhu))->access_request = ENABLE; 351 352 while (!((SEND_FRAME(p_mhu))->access_ready)) { 353 /* Wait in a loop for access ready signal to be high */ 354 ; 355 } 356 357 return MHU_V_2_X_ERR_NONE; 358 } 359 360 enum mhu_v2_x_error_t mhu_v2_x_close_transfer(const struct mhu_v2_x_dev_t *dev) 361 { 362 union mhu_v2_x_frame *p_mhu; 363 364 assert(dev != NULL); 365 366 p_mhu = (union mhu_v2_x_frame *)dev->base; 367 368 if (!(dev->is_initialized)) { 369 return MHU_V_2_X_ERR_NOT_INIT; 370 } 371 372 if (dev->frame != MHU_V2_X_SENDER_FRAME) { 373 return MHU_V_2_X_ERR_INVALID_ARG; 374 } 375 376 (SEND_FRAME(p_mhu))->access_request = DISABLE; 377 378 return MHU_V_2_X_ERR_NONE; 379 } 380