1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8  * @brief File containing register read/write specific definitions for the
9  * HAL Layer of the Wi-Fi driver.
10  */
11 
12 #include "common/pal.h"
13 #include "common/hal_api_common.h"
14 #include "common/hal_common.h"
15 
16 
hal_rpu_is_reg(unsigned int addr_val)17 static bool hal_rpu_is_reg(unsigned int addr_val)
18 {
19 	unsigned int addr_base = (addr_val & RPU_ADDR_MASK_BASE);
20 
21 	if ((addr_base == RPU_ADDR_SBUS_START) ||
22 	    (addr_base == RPU_ADDR_PBUS_START)) {
23 		return true;
24 	} else {
25 		return false;
26 	}
27 }
28 
29 
hal_rpu_reg_read(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned int * val,unsigned int rpu_reg_addr)30 enum nrf_wifi_status hal_rpu_reg_read(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
31 				      unsigned int *val,
32 				      unsigned int rpu_reg_addr)
33 {
34 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
35 	unsigned long addr_offset = 0;
36 
37 #ifdef NRF_WIFI_LOW_POWER
38 	unsigned long flags = 0;
39 #endif /* NRF_WIFI_LOW_POWER */
40 
41 	if (!hal_dev_ctx) {
42 		return status;
43 	}
44 
45 	if ((val == NULL) ||
46 	    !hal_rpu_is_reg(rpu_reg_addr)) {
47 		nrf_wifi_osal_log_err("%s: Invalid params, val = %p, rpu_reg (0x%x)",
48 				      __func__,
49 				      val,
50 				      rpu_reg_addr);
51 		return status;
52 	}
53 
54 	status = pal_rpu_addr_offset_get(rpu_reg_addr,
55 					 &addr_offset,
56 					 hal_dev_ctx->curr_proc);
57 
58 	if (status != NRF_WIFI_STATUS_SUCCESS) {
59 		nrf_wifi_osal_log_err("%s: pal_rpu_addr_offset_get failed",
60 				      __func__);
61 		return status;
62 	}
63 
64 #ifdef NRF_WIFI_LOW_POWER
65 	nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->rpu_ps_lock,
66 					&flags);
67 
68 	status = hal_rpu_ps_wake(hal_dev_ctx);
69 
70 	if (status != NRF_WIFI_STATUS_SUCCESS) {
71 		nrf_wifi_osal_log_err("%s: RPU wake failed",
72 				      __func__);
73 		goto out;
74 	}
75 #endif /* NRF_WIFI_LOW_POWER */
76 
77 	*val = nrf_wifi_bal_read_word(hal_dev_ctx->bal_dev_ctx,
78 				      addr_offset);
79 
80 	if (*val == 0xFFFFFFFF) {
81 		nrf_wifi_osal_log_err("%s: Error !! Value read at addr_offset = %lx is = %X",
82 				      __func__,
83 				      addr_offset,
84 				      *val);
85 		status = NRF_WIFI_STATUS_FAIL;
86 		goto out;
87 	}
88 
89 	status = NRF_WIFI_STATUS_SUCCESS;
90 out:
91 #ifdef NRF_WIFI_LOW_POWER
92 	nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->rpu_ps_lock,
93 				       &flags);
94 #endif /* NRF_WIFI_LOW_POWER */
95 
96 	return status;
97 }
98 
hal_rpu_reg_write(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned int rpu_reg_addr,unsigned int val)99 enum nrf_wifi_status hal_rpu_reg_write(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
100 				       unsigned int rpu_reg_addr,
101 				       unsigned int val)
102 {
103 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
104 	unsigned long addr_offset = 0;
105 
106 #ifdef NRF_WIFI_LOW_POWER
107 	unsigned long flags = 0;
108 #endif /* NRF_WIFI_LOW_POWER */
109 
110 	if (!hal_dev_ctx) {
111 		return status;
112 	}
113 
114 	if (!hal_rpu_is_reg(rpu_reg_addr)) {
115 		nrf_wifi_osal_log_err("%s: Invalid params, rpu_reg_addr (0x%X)",
116 				      __func__,
117 				      rpu_reg_addr);
118 		return status;
119 	}
120 
121 	status = pal_rpu_addr_offset_get(rpu_reg_addr,
122 					 &addr_offset,
123 					 hal_dev_ctx->curr_proc);
124 
125 	if (status != NRF_WIFI_STATUS_SUCCESS) {
126 		nrf_wifi_osal_log_err("%s: pal_rpu_get_region_offset failed",
127 				      __func__);
128 		return status;
129 	}
130 
131 #ifdef NRF_WIFI_LOW_POWER
132 	nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->rpu_ps_lock,
133 					&flags);
134 
135 	status = hal_rpu_ps_wake(hal_dev_ctx);
136 
137 	if (status != NRF_WIFI_STATUS_SUCCESS) {
138 		nrf_wifi_osal_log_err("%s: RPU wake failed",
139 				      __func__);
140 		goto out;
141 	}
142 #endif /* NRF_WIFI_LOW_POWER */
143 
144 	nrf_wifi_bal_write_word(hal_dev_ctx->bal_dev_ctx,
145 				addr_offset,
146 				val);
147 
148 	status = NRF_WIFI_STATUS_SUCCESS;
149 
150 #ifdef NRF_WIFI_LOW_POWER
151 out:
152 	nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->rpu_ps_lock,
153 				       &flags);
154 #endif /* NRF_WIFI_LOW_POWER */
155 
156 	return status;
157 }
158